начат отчет
This commit is contained in:
parent
89f567e365
commit
106ee680c1
|
|
@ -0,0 +1,259 @@
|
||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "d7f65344",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"# Отчёт \n",
|
||||||
|
"## Телефонный справочник: реализация и сравнение структур данных\n",
|
||||||
|
"\n",
|
||||||
|
"**Студент:** Коннова Е.А.\n",
|
||||||
|
"**Группа:** 429\n",
|
||||||
|
"**Дата:**"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "f69aa231",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## Введение\n",
|
||||||
|
"\n",
|
||||||
|
"### О чем работа.\n",
|
||||||
|
"В данной работе рассматриваются три базовые структуры данных:\n",
|
||||||
|
"- Связный список (LinkedList)\n",
|
||||||
|
"- Хеш-таблица (HashTable)\n",
|
||||||
|
"- Двоичное дерево поиска (BST)\n",
|
||||||
|
"\n",
|
||||||
|
"Они применяются для хранения записей телефонного справочника.\n",
|
||||||
|
"\n",
|
||||||
|
"### Цель всей работы\n",
|
||||||
|
"Реализовать три структуры данных «с нуля», применить их для хранения записей телефонного справочника и экспериментально сравнить производительность основных операций (вставка, поиск, удаление).\n",
|
||||||
|
"\n",
|
||||||
|
"### Задачи по достижению цели\n",
|
||||||
|
"1. Реализовать связный список с операциями insert, find, delete, list_all\n",
|
||||||
|
"2. Реализовать хеш-таблицу на основе связных списков\n",
|
||||||
|
"3. Реализовать двоичное дерево поиска\n",
|
||||||
|
"4. Сгенерировать тестовые данные (10000 записей)\n",
|
||||||
|
"5. Провести замеры времени для каждой структуры (5 повторений)\n",
|
||||||
|
"6. Сравнить результаты и сделать выводы"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "56e2f617",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## Часть 1. Общая информация о структурах данных\n",
|
||||||
|
"\n",
|
||||||
|
"### 1.1 Для неспециалистов\n",
|
||||||
|
"\n",
|
||||||
|
"**Что такое структура данных?**\n",
|
||||||
|
"Это способ организации и хранения данных в компьютере.\n",
|
||||||
|
"\n",
|
||||||
|
"**Три структуры из работы:**\n",
|
||||||
|
"\n",
|
||||||
|
"| Структура | Как работает | Пример из жизни |\n",
|
||||||
|
"|-----------|--------------|-----------------|\n",
|
||||||
|
"| Связный список | Цепочка элементов, где каждый знает следующий | Верёвка с узелками |\n",
|
||||||
|
"| Хеш-таблица | Массив корзин, элемент попадает в корзину по номеру | Картотека с ящиками |\n",
|
||||||
|
"| Двоичное дерево | Иерархическая структура: левые меньше, правые больше | Телефонный справочник |\n",
|
||||||
|
"\n",
|
||||||
|
"### 1.2 Обзор технологий\n",
|
||||||
|
"\n",
|
||||||
|
"**Связный список**\n",
|
||||||
|
"- Узел: `{'name': str, 'phone': str, 'next': None}`\n",
|
||||||
|
"- Вставка: O(1) в начало, O(n) в конец\n",
|
||||||
|
"- Поиск: O(n) - линейный обход\n",
|
||||||
|
"- Удаление: O(n) - сначала найти\n",
|
||||||
|
"\n",
|
||||||
|
"**Хеш-таблица**\n",
|
||||||
|
"- Корзины: список из None или голов списков\n",
|
||||||
|
"- Хеш-функция: `hash = (hash * 31 + ord(ch)) % size`\n",
|
||||||
|
"- Вставка/поиск/удаление: O(1) в среднем\n",
|
||||||
|
"\n",
|
||||||
|
"**Двоичное дерево поиска (BST)**\n",
|
||||||
|
"- Узел: `{'name': str, 'phone': str, 'left': None, 'right': None}`\n",
|
||||||
|
"- Вставка/поиск/удаление: O(log n) в среднем, O(n) в худшем\n",
|
||||||
|
"\n",
|
||||||
|
"### 1.3 Обоснование выбора подхода\n",
|
||||||
|
"\n",
|
||||||
|
"**Почему именно эти структуры?**\n",
|
||||||
|
"1. Они фундаментальны и изучаются в курсе\n",
|
||||||
|
"2. Показывают разные компромиссы (скорость vs порядок)\n",
|
||||||
|
"3. Позволяют наглядно сравнить производительность\n",
|
||||||
|
"\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "d9327709",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## Часть 2. Техническая реализация\n",
|
||||||
|
"\n",
|
||||||
|
"### 2.1 Постановка задачи\n",
|
||||||
|
"\n",
|
||||||
|
"Реализовать телефонный справочник с операциями:\n",
|
||||||
|
"- `insert(name, phone)` — добавить или обновить запись\n",
|
||||||
|
"- `find(name)` — вернуть телефон или None\n",
|
||||||
|
"- `delete(name)` — удалить запись\n",
|
||||||
|
"- `list_all()` — вернуть все записи, отсортированные по имени\n",
|
||||||
|
"\n",
|
||||||
|
"### 2.2 Верхнеуровневое решение\n",
|
||||||
|
"\n",
|
||||||
|
"**Связный список (LinkedList)**\n",
|
||||||
|
"- `ll_insert(head, name, phone)` — добавление в конец, возвращает голову\n",
|
||||||
|
"- `ll_find(head, name)` — линейный поиск, возвращает телефон или None\n",
|
||||||
|
"- `ll_delete(head, name)` — удаление с перепривязкой, возвращает голову\n",
|
||||||
|
"- `ll_list_all(head)` — сбор всех записей и сортировка\n",
|
||||||
|
"\n",
|
||||||
|
"**Хеш-таблица (HashTable)**\n",
|
||||||
|
"- `hash_function(name, size)` — ключ → номер корзины\n",
|
||||||
|
"- `ht_create(size)` — создание таблицы\n",
|
||||||
|
"- `ht_insert(buckets, name, phone)` — вызов ll_insert для нужной корзины\n",
|
||||||
|
"- `ht_find(buckets, name)` — вызов ll_find для нужной корзины\n",
|
||||||
|
"- `ht_delete(buckets, name)` — вызов ll_delete для нужной корзины\n",
|
||||||
|
"- `ht_list_all(buckets)` — сбор из всех корзин + сортировка\n",
|
||||||
|
"\n",
|
||||||
|
"**Двоичное дерево (BST)**\n",
|
||||||
|
"- `bst_insert(root, name, phone)` — итеративная вставка\n",
|
||||||
|
"- `bst_find(root, name)` — поиск\n",
|
||||||
|
"- `bst_delete(root, name)` — удаление с поиском преемника\n",
|
||||||
|
"- `bst_list_all(root)` — in-order обход (уже отсортировано)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "c1cd08d8",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## Часть 3. Эксперименты и результаты\n",
|
||||||
|
"\n",
|
||||||
|
"### 3.1 Инструменты и методика\n",
|
||||||
|
"\n",
|
||||||
|
"**Параметры эксперимента:**\n",
|
||||||
|
"- Количество записей: 10 000\n",
|
||||||
|
"- Количество повторений: 5\n",
|
||||||
|
"- Поиск: 100 существующих + 10 несуществующих\n",
|
||||||
|
"- Удаление: 50 случайных записей\n",
|
||||||
|
"- Режимы: случайный порядок, отсортированный порядок\n",
|
||||||
|
"\n",
|
||||||
|
"### 3.2 Результаты"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "94634c57",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"*Таблица 1 - Результаты экспериментов (среднее время в секундах)*"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "5689bbd0",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"### 3.3 Графики\n",
|
||||||
|
"\n",
|
||||||
|
"#### График 1: Время вставки 10000 записей\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"#### График 2: Время поиска 110 записей\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"#### График 3: Время удаления 50 записей\n",
|
||||||
|
"\n",
|
||||||
|
""
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "5561d9dd",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"### 3.4 Сравнение и анализ\n",
|
||||||
|
"\n",
|
||||||
|
"**Как порядок входных данных влияет на BST?**\n",
|
||||||
|
"\n",
|
||||||
|
"| Режим | Вставка | Поиск | Удаление |\n",
|
||||||
|
"|-------|---------|-------|----------|\n",
|
||||||
|
"| Случайный | 0.026 сек | 0.00026 сек | 0.00017 сек |\n",
|
||||||
|
"| Отсортированный | 4.931 сек | 0.047 сек | 0.023 сек |\n",
|
||||||
|
"\n",
|
||||||
|
"Вывод: На случайных данных BST работает быстро (O(log n)). На отсортированных данных BST вырождается в связный список (O(n)). Работает медленее в 190 раз.\n",
|
||||||
|
"\n",
|
||||||
|
"**Техническая ошибка:** Из-за ограничения глубины рекурсии в Python (1000 вызовов) рекурсивная реализация BST не смогла бы обработать 10000 записей. Поэтому все операции BST были реализованы итеративно.\n",
|
||||||
|
"\n",
|
||||||
|
"**Почему хеш-таблица не чувствительна к порядку?**\n",
|
||||||
|
"\n",
|
||||||
|
"Хеш-функция распределяет записи по корзинам независимо от порядка вставки. Распределение по корзинам равномерное.\n",
|
||||||
|
"\n",
|
||||||
|
"**Почему связный список всегда медленен при поиске?**\n",
|
||||||
|
"\n",
|
||||||
|
"Связный список не имеет индексов. Поэтому нужно перебирать элементы последовательно. Сложность поиска - O(n).\n",
|
||||||
|
"\n",
|
||||||
|
"**Как удаление работает в каждой структуре?**\n",
|
||||||
|
"\n",
|
||||||
|
"| Структура | Сложность |\n",
|
||||||
|
"|-----------|-----------|\n",
|
||||||
|
"| LinkedList | O(n) |\n",
|
||||||
|
"| HashTable | O(1) |\n",
|
||||||
|
"| BST | O(log n) / O(n) |\n",
|
||||||
|
"\n",
|
||||||
|
"В связных списках сначала нужно найти, потом перепривязать. В хеш-таблице сразу находишь корзину по хешу. В двоичном дереве нужно найти узел и перестроить поддеревья."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "a57d1502",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## Заключение\n",
|
||||||
|
"\n",
|
||||||
|
"### Выводы из каждой части\n",
|
||||||
|
"\n",
|
||||||
|
"**Из части 1:**\n",
|
||||||
|
"- Каждая структура имеет свои теоретические характеристики\n",
|
||||||
|
"- Связный список - прост, но медленен\n",
|
||||||
|
"- Хеш-таблица - быстра, но не сохраняет порядок\n",
|
||||||
|
"- BST - быстр и сохраняет порядок, но требует балансировки\n",
|
||||||
|
"\n",
|
||||||
|
"**Из части 2:**\n",
|
||||||
|
"- Все три структуры успешно реализованы\n",
|
||||||
|
"- Хеш-таблица использует связный список для корзин\n",
|
||||||
|
"- BST написан итеративно для избежания RecursionError\n",
|
||||||
|
"\n",
|
||||||
|
"**Из части 3:**\n",
|
||||||
|
"- Эксперименты подтвердили теоретические оценки\n",
|
||||||
|
"- BST на отсортированных данных деградирует\n",
|
||||||
|
"- Хеш-таблица стабильна независимо от порядка\n",
|
||||||
|
"\n",
|
||||||
|
"### Итоговая рекомендация\n",
|
||||||
|
"\n",
|
||||||
|
"| Сценарий | Рекомендация | Причина |\n",
|
||||||
|
"|----------|--------------|---------|\n",
|
||||||
|
"| Частый поиск по ключу | Хеш-таблица | O(1) |\n",
|
||||||
|
"| Частые вставки/удаления | Хеш-таблица | Стабильная скорость |\n",
|
||||||
|
"| Нужен отсортированный вывод | Сбалансированное дерево | In-order обход |\n",
|
||||||
|
"| Данные поступают отсортированно | Хеш-таблица | BST деградирует |\n",
|
||||||
|
"| Мало данных (<100) | Любая | Разница незаметна |\n",
|
||||||
|
"\n",
|
||||||
|
"**Для телефонного справочника лучший выбор - хеш-таблица.**"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"language_info": {
|
||||||
|
"name": "python"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 5
|
||||||
|
}
|
||||||
|
|
@ -9,15 +9,12 @@ os.makedirs('docs/data', exist_ok=True)
|
||||||
|
|
||||||
structures = ['LinkedList', 'HashTable', 'BST']
|
structures = ['LinkedList', 'HashTable', 'BST']
|
||||||
|
|
||||||
# Вставка 10000 записей
|
|
||||||
random_insert = [0.0037545, 0.015088, 0.026280]
|
random_insert = [0.0037545, 0.015088, 0.026280]
|
||||||
sorted_insert = [0.0017544, 0.011369, 4.930788]
|
sorted_insert = [0.0017544, 0.011369, 4.930788]
|
||||||
|
|
||||||
# Поиск 110 записей
|
|
||||||
random_search = [0.00000962, 0.0001646, 0.0002592]
|
random_search = [0.00000962, 0.0001646, 0.0002592]
|
||||||
sorted_search = [0.00000858, 0.00014016, 0.047126]
|
sorted_search = [0.00000858, 0.00014016, 0.047126]
|
||||||
|
|
||||||
# Удаление 50 записей
|
|
||||||
random_delete = [0.0000079, 0.00009824, 0.00016984]
|
random_delete = [0.0000079, 0.00009824, 0.00016984]
|
||||||
sorted_delete = [0.00000294, 0.00005878, 0.023013]
|
sorted_delete = [0.00000294, 0.00005878, 0.023013]
|
||||||
|
|
||||||
|
|
@ -56,7 +53,7 @@ ax.grid(True, alpha=0.3, axis='y')
|
||||||
plt.tight_layout()
|
plt.tight_layout()
|
||||||
plt.savefig('docs/data/graph_insert.png', dpi=150, bbox_inches='tight')
|
plt.savefig('docs/data/graph_insert.png', dpi=150, bbox_inches='tight')
|
||||||
plt.close()
|
plt.close()
|
||||||
print(" График 1 сохранён: docs/data/graph_insert.png")
|
|
||||||
|
|
||||||
# график поиск
|
# график поиск
|
||||||
fig, ax = plt.subplots(figsize=(12, 7))
|
fig, ax = plt.subplots(figsize=(12, 7))
|
||||||
|
|
@ -89,7 +86,7 @@ ax.grid(True, alpha=0.3, axis='y')
|
||||||
plt.tight_layout()
|
plt.tight_layout()
|
||||||
plt.savefig('docs/data/graph_search.png', dpi=150, bbox_inches='tight')
|
plt.savefig('docs/data/graph_search.png', dpi=150, bbox_inches='tight')
|
||||||
plt.close()
|
plt.close()
|
||||||
print(" График 2 сохранён: docs/data/graph_search.png")
|
|
||||||
|
|
||||||
# график удаление
|
# график удаление
|
||||||
fig, ax = plt.subplots(figsize=(12, 7))
|
fig, ax = plt.subplots(figsize=(12, 7))
|
||||||
|
|
@ -122,5 +119,5 @@ ax.grid(True, alpha=0.3, axis='y')
|
||||||
plt.tight_layout()
|
plt.tight_layout()
|
||||||
plt.savefig('docs/data/graph_delete.png', dpi=150, bbox_inches='tight')
|
plt.savefig('docs/data/graph_delete.png', dpi=150, bbox_inches='tight')
|
||||||
plt.close()
|
plt.close()
|
||||||
print(" График 3 сохранён: docs/data/graph_delete.png")
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,5 +32,3 @@ for i, row in enumerate(data):
|
||||||
plt.title('Результаты экспериментов (среднее время в секундах)', fontsize=14, fontweight='bold', pad=20)
|
plt.title('Результаты экспериментов (среднее время в секундах)', fontsize=14, fontweight='bold', pad=20)
|
||||||
plt.savefig('docs/data/table_results.png', dpi=200, bbox_inches='tight', facecolor='white')
|
plt.savefig('docs/data/table_results.png', dpi=200, bbox_inches='tight', facecolor='white')
|
||||||
plt.close()
|
plt.close()
|
||||||
|
|
||||||
print("Таблица сохранена: docs/data/table_results.png")
|
|
||||||
Loading…
Reference in New Issue
Block a user