Отчёт по лабораторной работе "Структуры данных"
1. Цель работы
Реализовать три структуры данных «с нуля» в процедурной парадигме (без классов), применить их для хранения записей телефонного справочника и экспериментально сравнить производительность основных операций: вставки, поиска и удаления.
Структуры данных:
Связный список (LinkedList) — узлы-словари, соединённые ссылками.
Хеш-таблица (HashTable) — массив корзин (1024 элемента) с цепочками через связный список.
Двоичное дерево поиска (BST) — рекурсивная / итеративная реализация через словари.
N = 10 000 записей вида User_00001, +7-000-0000001.
Два режима: случайный порядок (records_shuffled) и отсортированный (records_sorted).
Поиск: 100 гарантированно существующих имён + 10 несуществующих = 110 запросов.
Удаление: 50 случайных имён из набора.
Каждый замер повторяется 5 раз; записываются все замеры и среднее.
2. Результаты экспериментов
| structure |
mode |
operation |
run |
time_sec |
| LinkedList |
shuffled |
insert |
1 |
3.688133922999995 |
| LinkedList |
shuffled |
insert |
2 |
3.642716359000005 |
| LinkedList |
shuffled |
insert |
3 |
3.6362029409999934 |
| LinkedList |
shuffled |
insert |
4 |
3.5635424559999933 |
| LinkedList |
shuffled |
insert |
5 |
3.6936824539999975 |
| LinkedList |
shuffled |
find |
1 |
0.0404481799999985 |
| LinkedList |
shuffled |
find |
2 |
0.0415632419999951 |
| LinkedList |
shuffled |
find |
3 |
0.0408364839999961 |
| LinkedList |
shuffled |
find |
4 |
0.0409441910000083 |
| LinkedList |
shuffled |
find |
5 |
0.0409490519999877 |
| LinkedList |
shuffled |
delete |
1 |
0.020429828999994 |
| LinkedList |
shuffled |
delete |
2 |
0.0203125029999995 |
| LinkedList |
shuffled |
delete |
3 |
0.0205162980000039 |
| LinkedList |
shuffled |
delete |
4 |
0.0204522580000059 |
| LinkedList |
shuffled |
delete |
5 |
0.0204940820000132 |
| LinkedList |
sorted |
insert |
1 |
2.807388945 |
| LinkedList |
sorted |
insert |
2 |
2.6681887550000027 |
| LinkedList |
sorted |
insert |
3 |
2.7149360570000027 |
| LinkedList |
sorted |
insert |
4 |
2.586755936000003 |
| LinkedList |
sorted |
insert |
5 |
2.858489943000009 |
| LinkedList |
sorted |
find |
1 |
0.0301240860000007 |
| LinkedList |
sorted |
find |
2 |
0.0300124050000079 |
| LinkedList |
sorted |
find |
3 |
0.0301267250000023 |
| LinkedList |
sorted |
find |
4 |
0.0300742670000033 |
| LinkedList |
sorted |
find |
5 |
0.0304795409999769 |
| LinkedList |
sorted |
delete |
1 |
0.0176948809999828 |
| LinkedList |
sorted |
delete |
2 |
0.0186108259999855 |
| LinkedList |
sorted |
delete |
3 |
0.0183917109999924 |
| LinkedList |
sorted |
delete |
4 |
0.0183299800000042 |
| LinkedList |
sorted |
delete |
5 |
0.0202586389999908 |
| HashTable |
shuffled |
insert |
1 |
0.040671551999992 |
| HashTable |
shuffled |
insert |
2 |
0.0356988590000071 |
| HashTable |
shuffled |
insert |
3 |
0.034698187999993 |
| HashTable |
shuffled |
insert |
4 |
0.034897758999989 |
| HashTable |
shuffled |
insert |
5 |
0.0436747020000041 |
| HashTable |
shuffled |
find |
1 |
0.0003306420000228 |
| HashTable |
shuffled |
find |
2 |
0.0002776770000139 |
| HashTable |
shuffled |
find |
3 |
0.0002387590000125 |
| HashTable |
shuffled |
find |
4 |
0.0002413439999884 |
| HashTable |
shuffled |
find |
5 |
0.0002350800000101 |
| HashTable |
shuffled |
delete |
1 |
0.0009653390000039 |
| HashTable |
shuffled |
delete |
2 |
0.000182843999994 |
| HashTable |
shuffled |
delete |
3 |
0.000187277000009 |
| HashTable |
shuffled |
delete |
4 |
0.0001825169999847 |
| HashTable |
shuffled |
delete |
5 |
0.000182102999986 |
| HashTable |
sorted |
insert |
1 |
0.031514957000013 |
| HashTable |
sorted |
insert |
2 |
0.0317737780000015 |
| HashTable |
sorted |
insert |
3 |
0.0332209919999968 |
| HashTable |
sorted |
insert |
4 |
0.0438333349999879 |
| HashTable |
sorted |
insert |
5 |
0.0344081210000126 |
| HashTable |
sorted |
find |
1 |
0.0004218560000026 |
| HashTable |
sorted |
find |
2 |
0.0003256969999938 |
| HashTable |
sorted |
find |
3 |
0.0003048350000085 |
| HashTable |
sorted |
find |
4 |
0.000252023999991 |
| HashTable |
sorted |
find |
5 |
0.0002450770000166 |
| HashTable |
sorted |
delete |
1 |
0.0002077629999917 |
| HashTable |
sorted |
delete |
2 |
0.000197111999995 |
| HashTable |
sorted |
delete |
3 |
0.000204272000019 |
| HashTable |
sorted |
delete |
4 |
0.0001966060000029 |
| HashTable |
sorted |
delete |
5 |
0.0001917250000076 |
| BST |
shuffled |
insert |
1 |
0.0322367580000104 |
| BST |
shuffled |
insert |
2 |
0.0445325409999952 |
| BST |
shuffled |
insert |
3 |
0.0312052750000191 |
| BST |
shuffled |
insert |
4 |
0.0302206560000115 |
| BST |
shuffled |
insert |
5 |
0.0304544809999924 |
| BST |
shuffled |
find |
1 |
0.000256859999979 |
| BST |
shuffled |
find |
2 |
0.0001786029999948 |
| BST |
shuffled |
find |
3 |
0.0001869349999878 |
| BST |
shuffled |
find |
4 |
0.0001727730000027 |
| BST |
shuffled |
find |
5 |
0.0001574610000147 |
| BST |
shuffled |
delete |
1 |
0.0001869909999925 |
| BST |
shuffled |
delete |
2 |
0.0012688459999878 |
| BST |
shuffled |
delete |
3 |
0.0012691000000017 |
| BST |
shuffled |
delete |
4 |
0.001258899999982 |
| BST |
shuffled |
delete |
5 |
0.0013220630000034 |
| BST |
sorted |
insert |
1 |
12.957382101000007 |
| BST |
sorted |
insert |
2 |
12.10390555699999 |
| BST |
sorted |
insert |
3 |
12.698454105999986 |
| BST |
sorted |
insert |
4 |
12.181134653000017 |
| BST |
sorted |
insert |
5 |
12.952122806999997 |
| BST |
sorted |
find |
1 |
0.0432625550000125 |
| BST |
sorted |
find |
2 |
0.0455909260000169 |
| BST |
sorted |
find |
3 |
0.0434497109999938 |
| BST |
sorted |
find |
4 |
0.04326359800001 |
| BST |
sorted |
find |
5 |
0.0431787990000032 |
| BST |
sorted |
delete |
1 |
0.0546987289999947 |
| BST |
sorted |
delete |
2 |
0.0549414869999793 |
| BST |
sorted |
delete |
3 |
0.0549512879999838 |
| BST |
sorted |
delete |
4 |
0.0546492089999901 |
| BST |
sorted |
delete |
5 |
0.0542962790000274 |
| Графическое представление результатов приведено на рисунке ниже. |
|
|
|
|
[ ] |
|
|
|
|
3. Анализ результатов
3.1. Вставка
Связный список: проход по всему списку для поиска дубликата перед вставкой даёт O(n) на каждый элемент. При N = 10 000 это ≈50 млн операций сравнения — отсюда 3.6 с.
Хеш-таблица: хеш вычисляется за O(len(name)), поиск в корзине ≈ O(1). Итог — 0.037 с независимо от порядка.
BST на случайных данных: дерево остаётся примерно сбалансированным, высота ≈ log₂(10000) ≈ 13. Итог — 0.034 с. На отсортированных данных каждый новый элемент добавляется в правое поддерево, высота достигает N = 10 000 — полная деградация до O(n²) суммарно. Итог — 12.6 с (×373 замедление).
3.2. Поиск
Связный список: в среднем просматривает N/2 узлов. При 110 запросах — ≈550 000 сравнений. Время ≈ 0.04 с.
Хеш-таблица: поиск в корзине из ~10 элементов — практически мгновенно. Время ≈ 0.0003 с — в 130 раз быстрее связного списка.
BST: случайный порядок — log(N) шагов, ≈ 0.0002 с. Отсортированный — линейный поиск O(n), ≈ 0.044 с (сравнимо со связным списком).
3.3. Удаление
Связный список: необходим проход до удаляемого элемента — O(n). При 50 удалениях ≈ 0.02 с.
Хеш-таблица: O(1) в среднем — ≈ 0.0003 с.
BST: случайные данные — O(log n) ≈ 0.001 с. Отсортированные — O(n) ≈ 0.055 с.
3.4. Получение отсортированного списка
Связный список и хеш-таблица: сбор всех N элементов + Python sort — O(n log n). Практически одинаково для обеих структур.
BST: in-order обход уже возвращает отсортированный список — O(n), без дополнительной сортировки. При случайном вводе BST является наиболее эффективным для list_all.
4. Выводы и рекомендации
На основании экспериментов можно дать следующие практические рекомендации:
Частые вставки и поиск без упорядочивания → Хеш-таблица. Константное среднее время O(1) для всех операций, нечувствительность к порядку данных. Практически всегда лучший выбор для справочников, кэшей, индексов.
Данные нужны в отсортированном порядке (range queries, итерация по алфавиту) → Сбалансированное BST (AVL, красно-чёрное дерево) или B-дерево. Простая BST допустима только при случайном порядке вставки. На отсортированных данных деградирует до O(n).
Очень мало элементов или требуется простота реализации → Связный список. При N < 100 разница в скорости незначительна, а код минимальный.
BST (сбалансированный) vs Хеш-таблица: если нужно только find/insert/delete — хеш-таблица быстрее. Если нужны min/max, range-запросы, сортировка — BST предпочтительнее.
Итог: для реального телефонного справочника с операциями insert/find/delete оптимальна хеш-таблица. Если требуется регулярный вывод списка по алфавиту — BST (сбалансированное). Связный список применим только как учебная модель или для очень маленьких N.