diff --git a/KuznetsovYuM/docs/experiment_results.csv b/KuznetsovYuM/docs/experiment_results.csv new file mode 100644 index 0000000..86aa445 --- /dev/null +++ b/KuznetsovYuM/docs/experiment_results.csv @@ -0,0 +1,31 @@ +Structure,Mode,Repeat,Insert (sec),Search (sec),Delete (sec) +LinkedList,random,1,4.391112,0.026905,0.012824 +LinkedList,random,2,4.845220,0.031560,0.030583 +LinkedList,random,3,4.461536,0.030224,0.013461 +LinkedList,random,4,4.562402,0.028962,0.014101 +LinkedList,random,5,4.491418,0.040197,0.018795 +LinkedList,sorted,1,3.728189,0.023831,0.010369 +LinkedList,sorted,2,3.681244,0.023794,0.011584 +LinkedList,sorted,3,3.710309,0.025346,0.011397 +LinkedList,sorted,4,3.687962,0.027130,0.010611 +LinkedList,sorted,5,3.713101,0.026431,0.011425 +HashTable,random,1,0.056713,0.000387,0.000268 +HashTable,random,2,0.053692,0.000412,0.000199 +HashTable,random,3,0.053167,0.001272,0.000238 +HashTable,random,4,0.059468,0.000414,0.000174 +HashTable,random,5,0.052122,0.000918,0.000205 +HashTable,sorted,1,0.054478,0.000406,0.000157 +HashTable,sorted,2,0.052836,0.000398,0.000190 +HashTable,sorted,3,0.052295,0.000410,0.000177 +HashTable,sorted,4,0.053164,0.000447,0.000169 +HashTable,sorted,5,0.051903,0.000399,0.000179 +BST,random,1,0.024767,0.000204,0.000125 +BST,random,2,0.025908,0.000222,0.000119 +BST,random,3,0.025214,0.000223,0.000113 +BST,random,4,0.021233,0.000183,0.000111 +BST,random,5,0.022941,0.000277,0.000140 +BST,sorted,1,8.967227,0.081463,0.047105 +BST,sorted,2,8.873885,0.076518,0.042572 +BST,sorted,3,8.827521,0.066650,0.055038 +BST,sorted,4,8.722978,0.090392,0.045578 +BST,sorted,5,9.053348,0.088699,0.054090 diff --git a/KuznetsovYuM/docs/performance_comparison.png b/KuznetsovYuM/docs/performance_comparison.png new file mode 100644 index 0000000..411d420 Binary files /dev/null and b/KuznetsovYuM/docs/performance_comparison.png differ diff --git a/KuznetsovYuM/docs/report-1-st.md b/KuznetsovYuM/docs/report-1-st.md new file mode 100644 index 0000000..7baac1d --- /dev/null +++ b/KuznetsovYuM/docs/report-1-st.md @@ -0,0 +1,110 @@ +# Отчёт по лабораторной работе +## «Сравнение производительности структур данных на примере телефонного справочника» + +**Выполнил:** студент группы ... +**Цель работы:** реализовать три структуры данных (связный список, хеш-таблицу, двоичное дерево поиска) «с нуля» и экспериментально сравнить их производительность при операциях вставки, поиска и удаления записей телефонного справочника. + +--- + +## 1. Условия эксперимента + +- **Количество записей:** \( N = 10\,000 \) +- **Каждая запись:** уникальное имя вида `User_XYZW` и случайный телефон +- **Два режима подачи данных:** + - *Случайный порядок* – записи перемешаны + - *Отсортированный порядок* – записи идут строго по возрастанию имени +- **Измеряемые операции:** + - Вставка всех \( N \) записей + - Поиск 100 существующих + 10 несуществующих имён + - Удаление 50 случайных существующих записей +- **Повторения:** каждый эксперимент повторён 5 раз, результаты усреднены +- **Инструмент замера:** `time.perf_counter()` (секунды) + +Все структуры реализованы вручную на Python без использования встроенных типов (кроме базовых списков для хеш-таблицы). Код находится в файле `phonebook_structures.py`. + +--- + +## 2. Результаты измерений + +В таблице приведены **средние значения** времени (в секундах) по 5 запускам. + +| Структура | Режим | Вставка (с) | Поиск (с) | Удаление (с) | +|----------------|--------------|-------------|-----------|---------------| +| Связный список | случайный | 4.5503 | 0.0316 | 0.0180 | +| Связный список | отсортир. | 3.7042 | 0.0253 | 0.0111 | +| Хеш-таблица | случайный | 0.0550 | 0.00068 | 0.000217 | +| Хеш-таблица | отсортир. | 0.0529 | 0.00041 | 0.000174 | +| BST (ДДП) | случайный | 0.0240 | 0.000222 | 0.000122 | +| BST (ДДП) | отсортир. | 8.8890 | 0.0807 | 0.0489 | + +*Графическое представление результатов приведено на рисунке 1.* + +![Сравнение производительности структур данных](performance_comparison.png) + +*Рисунок 1 – Время выполнения операций для трёх структур в разных режимах подачи данных (логарифмическая шкала по вертикали для наглядности).* + +--- + +## 3. Анализ результатов + +### 3.1. Влияние порядка данных на BST + +Двоичное дерево поиска при вставке отсортированных данных вырождается в линейный список – каждый новый узел становится правым потомком предыдущего. Высота дерева достигает \( N \), и сложность всех операций падает с \( O(\log N) \) до \( O(N) \). Эксперимент ярко это подтверждает: + +- **Вставка** на отсортированных данных заняла **8.889 с** – это в **370 раз** медленнее, чем на случайных (0.024 с). +- **Поиск** замедлился в **360 раз** (0.0807 с против 0.000222 с). +- **Удаление** замедлилось в **400 раз** (0.0489 с против 0.000122 с). + +Такой эффект делает обычное двоичное дерево непригодным для данных, поступающих в упорядоченном виде, если не применять балансировку. + +### 3.2. Стабильность хеш-таблицы + +Хеш-таблица использует хеш-функцию, которая равномерно распределяет имена по корзинам независимо от их исходного порядка. Поэтому производительность почти не меняется: + +- Вставка: ~0.055 с (случайный) и ~0.053 с (отсортированный) – разница менее 5%. +- Поиск: 0.00068 с против 0.00041 с – небольшие колебания связаны со случайными коллизиями. +- Удаление: также стабильно. + +Это соответствует теоретической сложности \( O(1) \) в среднем для всех операций. + +### 3.3. Связный список – ожидаемо медленный + +Линейный поиск и вставка в конец дают сложность \( O(N) \) для всех операций: + +- Вставка на случайных данных: **4.55 с** – почти в 200 раз медленнее, чем у хеш-таблицы. +- Поиск: **0.0316 с** – на два порядка медленнее, чем у BST на случайных данных. +- Отсортированный порядок даёт небольшой выигрыш во вставке (3.7 с), потому что при вставке в конец не нужно сравнивать имена для поиска дубликатов? На самом деле в текущей реализации при вставке всё равно выполняется проход по всем элементам для проверки существования имени, поэтому разница не принципиальна. + +Связный список абсолютно не подходит для больших объёмов данных, если нужен частый поиск. + +### 3.4. Сравнение удаления + +- **Связный список** – удаление требует линейного поиска, время ~0.018 с (сопоставимо с поиском). +- **Хеш-таблица** – удаление за \( O(1) \) в среднем: ~0.0002 с. +- **BST** на случайных данных – очень быстрое удаление (~0.00012 с), но на отсортированных падает до 0.049 с (из-за вырождения). + +--- + +## 4. Выводы и практические рекомендации + +На основе полученных результатов можно сформулировать следующие правила выбора структуры данных: + +| Если важно... | Рекомендуемая структура | +|------------------------------------------------|---------------------------------------------| +| Максимальная скорость поиска, вставки, удаления и порядок данных заранее неизвестен | **Хеш-таблица** (с хорошей хеш-функцией) | +| Нужно часто выводить данные в отсортированном виде, и данные поступают в случайном порядке | **Сбалансированное дерево** (AVL, красно-чёрное) | +| Данные поступают в отсортированном виде, но нужен отсортированный вывод | **Плохое обычное BST** использовать нельзя – только после перемешивания или с балансировкой | +| Объём данных очень мал (< 100 записей) и простота реализации важнее скорости | **Связный список** | + +**Конкретные выводы по эксперименту:** + +1. **Хеш-таблица** показала стабильно высокую производительность во всех режимах. Это лучший выбор для телефонного справочника, если не требуется выдача записей в алфавитном порядке (в задании `list_all()` сортирует отдельно, что приемлемо). +2. **Двоичное дерево поиска** на случайных данных работает почти так же быстро, как хеш-таблица, но полностью деградирует на отсортированных. Это демонстрирует необходимость использования самобалансирующихся деревьев в реальных приложениях (например, `dict` в Python внутри реализован как хеш-таблица, а `SortedDict` – как дерево). +3. **Связный список** непригоден для практического использования при \( N > 1000 \) из-за линейной сложности основных операций. + +**Итог:** для телефонного справочника с типичной нагрузкой (много поисков, частые вставки) оптимальной структурой является **хеш-таблица**. Если же требуется постоянно поддерживать данные в отсортированном виде (например, для автодополнения), то следует применять **сбалансированное дерево поиска**. + +--- + +*Дата выполнения эксперимента:* 22 мая 2026 г. +*Файлы результатов:* `experiment_results.csv`, `performance_comparison.png`