2026-rff_mp/MashinDD/lab1/docs/report.md
2026-05-11 16:40:10 +03:00

8.1 KiB
Raw Blame History

Отчёт: Задание 1 — Структуры данных

Цель работы

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

Структуры данных:

  • Связный список (LinkedList)
  • Хеш-таблица (HashTable)
  • Двоичное дерево поиска (BST)

Реализация

Файловая структура

task1/
├── phone_book.py      # все три структуры данных
├── benchmark.py       # генерация данных + замеры
├── plot_results.py    # построение графиков
└── docs/
    ├── report.md      # этот отчёт
    └── data/
        ├── results.csv
        ├── comparison_by_operation.png
        └── sorted_vs_random.png

Ключевые решения реализации

1. Связный список

Узел — Python-словарь: {'name': 'Имя', 'phone': '123', 'next': None}.

Вставка добавляет в начало списка за O(1) (если имя не существует), а при обновлении — проходит по списку O(n). Поиск и удаление — всегда O(n), так как нет случайного доступа.

2. Хеш-таблица

Массив из 256 бакетов. Каждый бакет — голова связного списка (цепочки для разрешения коллизий). Хеш-функция: стандартный hash(name) % size. Операции в среднем O(1), при коллизиях — O(k), где k — длина цепочки.

3. Двоичное дерево поиска (BST)

Узел: {'name': 'Имя', 'phone': '123', 'left': None, 'right': None}. Ключ сравнения — имя лексикографически. Вставка и поиск итеративные. Удаление рекурсивное (замена минимальным узлом правого поддерева). In-order обход даёт отсортированный список.


Экспериментальная часть

Параметры эксперимента

Параметр Значение
Количество записей (N) 10 000
Повторений каждого замера 5
Поисковых запросов 110 (100 существующих + 10 несуществующих)
Удалений 50
Размер хеш-таблицы 256 бакетов

Два варианта входных данных:

  • records_shuffled — случайный порядок (перемешанные записи)
  • records_sorted — отсортированный по имени (по алфавиту)

Результаты

Таблица средних времён (секунды)

Структура Режим Вставка (с) Поиск 110 (с) Удаление 50 (с)
LinkedList случайный 2.541985 0.034289 0.020349
LinkedList сортированный 2.208557 0.025340 0.016424
HashTable случайный 0.018235 0.000214 0.000120
HashTable сортированный 0.016163 0.000207 0.000124
BST случайный 0.017192 0.000145 0.000104
BST сортированный 3.854338 0.033498 0.045823

Графики

Сравнение по операциям

Влияние порядка данных


Анализ результатов

1. Связный список — всегда медленный поиск

Вставка в список занимает ~2.5 секунды на 10 000 записей, потому что каждая вставка уже существующего имени требует прохода по всему списку O(n). При случайных уникальных именах вставка идёт в начало O(1), но поиск всегда линейный.

Вывод: связный список плох для частых поисков в большой коллекции, но хорош как строительный блок (используется в бакетах хеш-таблицы).

2. Хеш-таблица — нечувствительна к порядку данных

Хеш-таблица показала одинаковые результаты при случайном и отсортированном порядке:

  • Вставка: ~0.017 с (в ~150 раз быстрее LinkedList)
  • Поиск: ~0.0002 с (в ~160 раз быстрее LinkedList)

Это объясняется природой хеширования: порядок вставки не влияет на распределение по бакетам. Ключ всегда попадает в предсказуемый бакет за O(1).

3. BST деградирует на отсортированных данных

Это самый наглядный результат эксперимента:

Случайный Сортированный Разница
BST insert 0.017 с 3.854 с ×225
BST find 0.000145 с 0.033 с ×231

Причина: при вставке отсортированных данных BST вырождается в односвязный список — каждый новый элемент больше предыдущего и уходит всегда в правое поддерево. Высота дерева становится O(n) вместо O(log n). Поиск и удаление тоже деградируют до O(n).

4. Сравнение операции delete

При случайных данных BST удаляет за ~0.0001 с (log n). При сортированных — ~0.046 с (деградация до линейного). HashTable стабильна: ~0.00012 с в обоих случаях.


Выводы и рекомендации

Когда какую структуру использовать?

Сценарий Рекомендация
Частый поиск по имени HashTable или BST (случайные данные)
Данные приходят отсортированными HashTable (BST деградирует!)
Нужен отсортированный список BST (in-order обход — бесплатный)
Частые вставки/удаления + поиск HashTable
Минимальная память, простота LinkedList (для малых N)
Диапазонные запросы (все имена AM) BST

Сложности операций

Структура Insert Find Delete List (sorted)
LinkedList O(n) O(n) O(n) O(n log n)
HashTable O(1) avg O(1) avg O(1) avg O(n log n)
BST (сбалансированный) O(log n) O(log n) O(log n) O(n)
BST (вырожденный) O(n) O(n) O(n) O(n)

Главный вывод

HashTable — лучший выбор для телефонного справочника при частых вставках и поисках. BST лучше HashTable только если нужен отсортированный вывод без дополнительной сортировки — но при условии случайного порядка вставки или использования самобалансирующегося дерева (AVL, Red-Black).