forked from UNN/2026-rff_mp
164 lines
11 KiB
Plaintext
164 lines
11 KiB
Plaintext
{
|
||
"cells": [
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "f058dc2c",
|
||
"metadata": {},
|
||
"source": [
|
||
"# Отчёт: Задание 1 — Структуры данных\n",
|
||
"\n",
|
||
"## Цель работы\n",
|
||
"\n",
|
||
"Разработать три структуры данных «с нуля» в процедурном стиле (без ООП), применить их для хранения записей телефонной книги и провести экспериментальное сравнение производительности ключевых операций.\n",
|
||
"\n",
|
||
"**Структуры данных:**\n",
|
||
"- Связный список (LinkedList)\n",
|
||
"- Хеш-таблица (HashTable)\n",
|
||
"- Двоичное дерево поиска (BST)\n",
|
||
"\n",
|
||
"---\n",
|
||
"\n",
|
||
"## Реализация\n",
|
||
"\n",
|
||
"### Основные технические решения\n",
|
||
"\n",
|
||
"#### 1. Связный список\n",
|
||
"\n",
|
||
"Узел реализован как Python-словарь: `{'name': 'Имя', 'phone': '123', 'next': None}`.\n",
|
||
"\n",
|
||
"Новые элементы добавляются **в конец** списка за O(1) (без проверки на дубликаты имени). Поиск и удаление работают за линейное время O(n) из-за отсутствия прямого доступа по индексу.\n",
|
||
"\n",
|
||
"#### 2. Хеш-таблица\n",
|
||
"\n",
|
||
"Фиксированный массив на **1000 корзин**. Каждая корзина — указатель на связный список (метод цепочек). Хеш-функция: полиномиальная с основанием 31, свёрнутая по модулю размера таблицы. Среднее время операций O(1), при коллизиях — O(k), где k — длина цепочки.\n",
|
||
"\n",
|
||
"#### 3. Двоичное дерево поиска (BST)\n",
|
||
"\n",
|
||
"Узел: `{'name': 'Имя', 'phone': '123', 'left': None, 'right': None}`. Сравнение ключей — лексикографическое по полю `name`. Вставка и поиск реализованы итеративно. Удаление — с заменой на минимальный узел правого поддерева. Обход в глубину даёт отсортированный список.\n",
|
||
"\n",
|
||
"---\n",
|
||
"\n",
|
||
"## Экспериментальная часть\n",
|
||
"\n",
|
||
"### Условия проведения замеров\n",
|
||
"\n",
|
||
"| Параметр | Значение |\n",
|
||
"|---|---|\n",
|
||
"| Количество записей (N) | 10 000 |\n",
|
||
"| Количество замеров на операцию | 5 |\n",
|
||
"| Поисковых запросов | 110 (100 существующих + 10 отсутствующих) |\n",
|
||
"| Удалений | 50 |\n",
|
||
"| Размер хеш-таблицы | 1000 корзин |\n",
|
||
"\n",
|
||
"**Два набора данных:**\n",
|
||
"- `records_shuffled` — случайный порядок записей\n",
|
||
"- `records_sorted` — упорядоченный по имени (алфавитный порядок)\n",
|
||
"\n",
|
||
"---\n",
|
||
"\n",
|
||
"## Результаты\n",
|
||
"\n",
|
||
"### Среднее время выполнения (секунды)\n",
|
||
"\n",
|
||
"| Структура | Режим | Вставка (10000) | Поиск (110) | Удаление (50) |\n",
|
||
"|-----------|-------|----------------|-------------|---------------|\n",
|
||
"| LinkedList | случайный | 0.001383 | 0.00000514 | 0.00000234 |\n",
|
||
"| LinkedList | отсортированный | 0.001167 | 0.00000500 | 0.00000230 |\n",
|
||
"| HashTable | случайный | 0.010394 | 0.00009380 | 0.00004332 |\n",
|
||
"| HashTable | отсортированный | 0.009557 | 0.00009298 | 0.00004388 |\n",
|
||
"| BST | случайный | 0.015142 | 0.00013682 | 0.00007188 |\n",
|
||
"| **BST** | **отсортированный** | **4.19062** | **0.030306** | **0.016941** |\n",
|
||
"\n",
|
||
"### Визуализация\n",
|
||
"\n",
|
||
"\n",
|
||
"\n",
|
||
"\n",
|
||
"\n",
|
||
"\n",
|
||
"\n",
|
||
"\n",
|
||
"\n",
|
||
"---\n",
|
||
"\n",
|
||
"## Анализ результатов\n",
|
||
"\n",
|
||
"### 1. Связный список — сверхбыстрая вставка, но линейный поиск\n",
|
||
"\n",
|
||
"- **Вставка** выполняется за **~0.0012 с** на 10000 элементов, так как добавление происходит в конец списка без проверки дубликатов (O(1) на операцию).\n",
|
||
"- **Поиск** и **удаление** в замерах показали микросекунды, но это следствие малого количества операций (110 поисков, 50 удалений) и того, что искомые записи находятся в начале списка. В худшем случае (поиск отсутствующего элемента) сложность остаётся O(n).\n",
|
||
"\n",
|
||
"**Вывод:** связный список эффективен только при очень малых объёмах данных или когда вставка — единственная частая операция.\n",
|
||
"\n",
|
||
"### 2. Хеш-таблица — стабильная производительность\n",
|
||
"\n",
|
||
"Хеш-таблица демонстрирует **устойчивость к порядку входных данных**:\n",
|
||
"- Вставка: ~0.010 с (быстрее BST на случайных данных, но медленнее LinkedList)\n",
|
||
"- Поиск: ~0.000094 с (в 18 раз быстрее BST на случайных)\n",
|
||
"- Удаление: ~0.000043 с (в 1.6 раза быстрее BST)\n",
|
||
"\n",
|
||
"Размер таблицы (1000 корзин) обеспечивает равномерное распределение ключей, поэтому производительность остаётся стабильной.\n",
|
||
"\n",
|
||
"### 3. BST катастрофически деградирует на упорядоченных данных\n",
|
||
"\n",
|
||
"Самый показательный результат эксперимента:\n",
|
||
"\n",
|
||
"| Операция | Случайный порядок | Отсортированный порядок | Ухудшение |\n",
|
||
"|----------|------------------|------------------------|-----------|\n",
|
||
"| Вставка | 0.01514 с | **4.19062 с** | **×277** |\n",
|
||
"| Поиск | 0.0001368 с | **0.03031 с** | **×221** |\n",
|
||
"| Удаление | 0.0000719 с | **0.01694 с** | **×236** |\n",
|
||
"\n",
|
||
"**Причина:** при вставке отсортированных данных дерево вырождается в линейный список — каждый новый элемент больше предыдущего и помещается только в правую ветку. Высота дерева становится O(n) вместо O(log n), что превращает все операции в линейные.\n",
|
||
"\n",
|
||
"### 4. Сравнение с теоретическими ожиданиями\n",
|
||
"\n",
|
||
"| Структура | Теоретическая вставка | Фактическая (случ./сорт.) | \n",
|
||
"|-----------|----------------------|---------------------------|\n",
|
||
"| LinkedList | O(1) (в конец) | 0.0014 с / 0.0012 с |\n",
|
||
"| HashTable | O(1) в среднем | 0.0104 с / 0.0096 с |\n",
|
||
"| BST | O(log n) в среднем | 0.0151 с (случ.) |\n",
|
||
"| BST | O(n) в худшем | 4.19 с (сорт.) |\n",
|
||
"\n",
|
||
"---\n",
|
||
"\n",
|
||
"## Выводы и практические рекомендации\n",
|
||
"\n",
|
||
"### Выбор структуры в зависимости от задачи\n",
|
||
"\n",
|
||
"| Сценарий | Рекомендация |\n",
|
||
"|----------|--------------|\n",
|
||
"| **Частый поиск по ключу** | HashTable (быстрее всего) |\n",
|
||
"| **Данные поступают упорядоченно** | HashTable (BST непригоден) |\n",
|
||
"| **Только вставка и редкий поиск** | LinkedList (самая быстрая вставка) |\n",
|
||
"| **Требуется отсортированный вывод** | BST (обход даёт порядок за O(n)) |\n",
|
||
"| **Сбалансированные операции** | HashTable |\n",
|
||
"| **Диапазонные запросы** (например, А–М) | BST (при условии балансировки) |\n",
|
||
"\n",
|
||
"### Теоретическая сложность операций \n",
|
||
"| Структура | Insert | Find | Delete | Обход (отсорт.) |\n",
|
||
"|-----------|--------|------|--------|-----------------|\n",
|
||
"| LinkedList (в конец) | O(1) | O(n) | O(n) | O(n log n) |\n",
|
||
"| HashTable | O(1) | O(1) | O(1) | O(n log n) |\n",
|
||
"| BST (сбалансированный) | O(log n) | O(log n) | O(log n) | O(n) |\n",
|
||
"| BST (вырожденный) | O(n) | O(n) | O(n) | O(n) |\n",
|
||
"\n",
|
||
"### Ключевой вывод\n",
|
||
"\n",
|
||
"Для телефонного справочника с частыми поисками и обновлениями оптимальный выбор — **хеш-таблица**. Она обеспечивает предсказуемую скорость вне зависимости от порядка данных.\n",
|
||
"\n",
|
||
"Обычный **связный список** полезен только как вспомогательная структура (например, для цепочек в хеш-таблице) или при минимальном объёме данных.\n",
|
||
"\n",
|
||
"**Двоичное дерево поиска** без самобалансировки опасно использовать с реальными данными, которые часто бывают частично или полностью упорядоченными. В таких случаях необходимо применять AVL или красно-чёрные деревья.\n"
|
||
]
|
||
}
|
||
],
|
||
"metadata": {
|
||
"language_info": {
|
||
"name": "python"
|
||
}
|
||
},
|
||
"nbformat": 4,
|
||
"nbformat_minor": 5
|
||
}
|