111 lines
10 KiB
Markdown
111 lines
10 KiB
Markdown
# Отчёт по лабораторной работе
|
||
## «Сравнение производительности структур данных на примере телефонного справочника»
|
||
|
||
**Выполнил:** студент группы ...
|
||
**Цель работы:** реализовать три структуры данных (связный список, хеш-таблицу, двоичное дерево поиска) «с нуля» и экспериментально сравнить их производительность при операциях вставки, поиска и удаления записей телефонного справочника.
|
||
|
||
---
|
||
|
||
## 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.*
|
||
|
||

|
||
|
||
*Рисунок 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`
|