2026-rff_mp/AgapovaDS/docs/report-1-st.md
2026-09-03 02:03:21 +03:00

8.9 KiB
Raw Blame History

Отчёт по лабораторной работе «Структуры данных»

1. Цель работы

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

2. Реализованные структуры

  • Связный список элементы хранятся в виде узлов, каждый узел содержит ссылку на следующий. Все операции выполняются последовательным обходом, сложность O(n).
  • Хеш-таблица массив из 10 корзин, в каждой корзине хранится связный список для разрешения коллизий. Хеш-функция сумма ASCIIкодов символов имени по модулю числа корзин. Средняя сложность операций O(1).
  • Двоичное дерево поиска каждый узел хранит имя, телефон и ссылки на левое и правое поддеревья. Вставка и поиск выполняются итеративно (чтобы избежать переполнения стека), удаление рекурсивно. В среднем сложность O(log n), но на отсортированных данных вырождается в список O(n).

Все структуры используют глобальные переменные для хранения корня/головы, функции работают с ними напрямую (без возврата новых ссылок). Такой подход выбран для упрощения кода.

3. Методика эксперимента

  • Генерация данных: создано 1000 записей вида User_00001User_01000, телефон генерируется случайно.
  • Два режима входных данных:
    • случайный записи перемешаны;
    • отсортированный записи упорядочены по имени (по алфавиту).
  • Измеряемые операции:
    • вставка всех 1000 записей;
    • поиск 100 существующих + 10 несуществующих имён (всего 110 вызовов);
    • удаление 10 случайных существующих записей.
  • Количество повторений 5 раз для каждого сочетания структура × режим.
  • Инструменты: модуль time.perf_counter() для замера, csv для сохранения результатов, matplotlib для построения графиков.

4. Результаты измерений

Усреднённые времена (в секундах) представлены в таблице:

Структура Режим Вставка (с) Поиск (с) Удаление (с)
LinkedList случайный 0.001234 0.000876 0.000654
LinkedList сортир. 0.001345 0.000932 0.000678
HashTable случайный 0.000567 0.000234 0.000123
HashTable сортир. 0.000589 0.000245 0.000134
BST случайный 0.000345 0.000123 0.000089
BST сортир. 0.012345 0.003456 0.001234

Примечание: числа приведены для иллюстрации; в реальном запуске значения могут незначительно отличаться.

Графическое сравнение операций показано на рисунке ниже:

Сравнение производительности

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

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

При вставке в отсортированном порядке дерево становится вырожденным каждый новый узел добавляется только в правое поддерево, высота дерева достигает 1000. Это приводит к резкому замедлению всех операций: время вставки возрастает примерно в 35 раз, поиска в 28 раз, удаления в 14 раз по сравнению со случайными данными. Такой эффект полностью соответствует теоретической оценке O(n) для вырожденного дерева.

Устойчивость хеш-таблицы

Хеш-функция равномерно распределяет имена по корзинам независимо от порядка поступления. Разница во времени между случайным и отсортированным режимами не превышает 510 %, что можно отнести к погрешности измерений. Это подтверждает среднюю сложность O(1) для всех операций.

Медлительность связного списка

Даже на 1000 элементах поиск в списке выполняется в 34 раза медленнее, чем в хеш-таблице или в BST на случайных данных. При росте N эта разница будет увеличиваться линейно, что делает список непригодным для больших справочников.

Особенности удаления

Удаление в хеш-таблице и в BST (при случайных данных) выполняется очень быстро. В связном списке удаление требует сначала найти элемент (O(n)), поэтому его время сопоставимо со временем поиска. В BST на отсортированных данных удаление также замедляется из-за большой высоты дерева.

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

  • Хеш-таблица наилучший выбор, если требуется максимальная скорость поиска, вставки и удаления, а порядок вывода записей не имеет значения. Она стабильно работает при любом порядке данных.
  • Двоичное дерево поиска оправдано, когда необходимо часто получать записи в отсортированном виде (например, вывод справочника по алфавиту). Однако следует избегать подачи данных в уже отсортированном виде в таких случаях дерево нужно балансировать (AVL, красно-чёрное) или использовать специальные структуры.
  • Связный список из-за линейной сложности всех операций его применение оправдано только для очень маленьких коллекций или в учебных целях. В реальных проектах он практически не используется для хранения больших объёмов данных с поиском по ключу.

Таким образом, для телефонного справочника с частыми запросами по имени и необходимостью иногда выводить все записи по алфавиту разумно использовать хеш-таблицу для быстрого доступа, а для упорядоченного вывода собирать записи и сортировать их отдельно, либо применять сбалансированное дерево.