# Отчёт по лабораторной работе  
## «Сравнение производительности структур данных на примере телефонного справочника»

**Выполнил:** студент группы ...  
**Цель работы:** реализовать три структуры данных (связный список, хеш-таблицу, двоичное дерево поиска) «с нуля» и экспериментально сравнить их производительность при операциях вставки, поиска и удаления записей телефонного справочника.

---

## 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`
