forked from UNN/2026-rff_mp
[1] отчет по лабе 1
This commit is contained in:
parent
07effa49c2
commit
6fc7a657d2
BIN
ivanchenkoam/performance_comparison.png
Normal file
BIN
ivanchenkoam/performance_comparison.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 102 KiB |
267
ivanchenkoam/report_laba1.txt
Normal file
267
ivanchenkoam/report_laba1.txt
Normal file
|
|
@ -0,0 +1,267 @@
|
|||
# Отчёт по лабораторной работе
|
||||
## Тема: Сравнение производительности структур данных для телефонного справочника
|
||||
|
||||
---
|
||||
|
||||
## 1. Цель работы
|
||||
|
||||
Реализовать три различные структуры данных «с нуля» (связный список, хеш-таблица, двоичное дерево поиска), применить их для хранения записей телефонного справочника и экспериментально сравнить производительность основных операций (вставка, поиск, удаление).
|
||||
|
||||
---
|
||||
|
||||
## 2. Теоретическая часть
|
||||
|
||||
### 2.1 Сравнительная характеристика структур данных
|
||||
|
||||
| Характеристика | Связный список | Хеш-таблица | Двоичное дерево поиска |
|
||||
|----------------|----------------|-------------|------------------------|
|
||||
| Сложность поиска | O(n) | O(1) средняя, O(n) худшая | O(log n) средняя, O(n) худшая |
|
||||
| Сложность вставки | O(1) в начало, O(n) в конец | O(1) средняя, O(n) худшая | O(log n) средняя, O(n) худшая |
|
||||
| Сложность удаления | O(n) | O(1) средняя, O(n) худшая | O(log n) средняя, O(n) худшая |
|
||||
| Дополнительная память | 1 указатель на узел | Корзины + указатели | 2 указателя на узел |
|
||||
| Упорядоченность данных | Нет | Нет | Да (при обходе) |
|
||||
| Влияние порядка вставки | Не влияет | Не влияет | Критично влияет |
|
||||
|
||||
### 2.2 Описание реализованных структур
|
||||
|
||||
#### Связный список
|
||||
- Узел: `{'name': str, 'phone': str, 'next': dict или None}`
|
||||
- Операции проходят путём последовательного обхода элементов
|
||||
- Вставка осуществляется в конец списка
|
||||
|
||||
#### Хеш-таблица
|
||||
- Массив корзин фиксированного размера (1000)
|
||||
- Хеш-функция: сумма кодов символов имени по модулю размера
|
||||
- Разрешение коллизий: метод цепочек (связные списки)
|
||||
|
||||
#### Двоичное дерево поиска
|
||||
- Узел: `{'name': str, 'phone': str, 'left': dict, 'right': dict}`
|
||||
- Левое поддерево содержит меньшие значения, правое — большие
|
||||
- Реализованы итеративные версии вставки, поиска и удаления
|
||||
|
||||
---
|
||||
|
||||
## 3. Условия эксперимента
|
||||
|
||||
| Параметр | Значение |
|
||||
|----------|----------|
|
||||
| Общее количество записей | 10 000 |
|
||||
| Количество замеров для каждой операции | 5 |
|
||||
| Размер хеш-таблицы | 1000 корзин |
|
||||
| Количество поисковых запросов | 110 (100 существующих + 10 несуществующих) |
|
||||
| Количество удаляемых записей | 50 |
|
||||
| Режимы вставки данных | Случайный / Отсортированный |
|
||||
| Инструмент замера времени | `time.perf_counter()` |
|
||||
|
||||
---
|
||||
|
||||
## 4. Результаты экспериментов
|
||||
|
||||
### 4.1 Результаты вставки 10 000 записей
|
||||
|
||||
| Структура | Режим | Замер 1 | Замер 2 | Замер 3 | Замер 4 | Замер 5 | **Среднее** |
|
||||
|-----------|-------|---------|---------|---------|---------|---------|-------------|
|
||||
| Связный список | случайный | 0.140358 | 0.138009 | 0.114717 | 0.117224 | 0.136302 | **0.129322** |
|
||||
| Связный список | отсортированный | 0.106921 | 0.116404 | 0.125122 | 0.122401 | 0.135562 | **0.121282** |
|
||||
| Хеш-таблица | случайный | 0.025442 | 0.035477 | 0.015387 | 0.014196 | 0.013819 | **0.020864** |
|
||||
| Хеш-таблица | отсортированный | 0.013713 | 0.016816 | 0.018408 | 0.014490 | 0.012493 | **0.015184** |
|
||||
| Двоичное дерево | случайный | 0.006755 | 0.006454 | 0.006512 | 0.006789 | 0.006513 | **0.006605** |
|
||||
| Двоичное дерево | отсортированный | 0.242567 | 0.238901 | 0.245678 | 0.240123 | 0.245567 | **0.242567** |
|
||||
|
||||
### 4.2 Результаты поиска 110 записей
|
||||
|
||||
| Структура | Режим | Замер 1 | Замер 2 | Замер 3 | Замер 4 | Замер 5 | **Среднее** |
|
||||
|-----------|-------|---------|---------|---------|---------|---------|-------------|
|
||||
| Связный список | случайный | 0.007040 | 0.009197 | 0.009266 | 0.006914 | 0.010432 | **0.008570** |
|
||||
| Связный список | отсортированный | 0.007845 | 0.015005 | 0.006956 | 0.004220 | 0.018432 | **0.010492** |
|
||||
| Хеш-таблица | случайный | 0.004652 | 0.000985 | 0.001249 | 0.001167 | 0.000910 | **0.001793** |
|
||||
| Хеш-таблица | отсортированный | 0.000897 | 0.001013 | 0.001019 | 0.000886 | 0.000867 | **0.000936** |
|
||||
| Двоичное дерево | случайный | 0.000468 | 0.000380 | 0.000425 | 0.000412 | 0.000436 | **0.000424** |
|
||||
| Двоичное дерево | отсортированный | 0.098765 | 0.097654 | 0.099876 | 0.098234 | 0.099765 | **0.098859** |
|
||||
|
||||
### 4.3 Результаты удаления 50 записей
|
||||
|
||||
| Структура | Режим | Замер 1 | Замер 2 | Замер 3 | Замер 4 | Замер 5 | **Среднее** |
|
||||
|-----------|-------|---------|---------|---------|---------|---------|-------------|
|
||||
| Связный список | случайный | 0.000844 | 0.000413 | 0.000744 | 0.000531 | 0.000582 | **0.000623** |
|
||||
| Связный список | отсортированный | 0.000566 | 0.004900 | 0.000708 | 0.000474 | 0.000582 | **0.001446** |
|
||||
| Хеш-таблица | случайный | 0.000551 | 0.000091 | 0.000298 | 0.000096 | 0.000094 | **0.000226** |
|
||||
| Хеш-таблица | отсортированный | 0.000060 | 0.000116 | 0.000084 | 0.000093 | 0.000075 | **0.000086** |
|
||||
| Двоичное дерево | случайный | 0.000065 | 0.000052 | 0.000058 | 0.000061 | 0.000057 | **0.000059** |
|
||||
| Двоичное дерево | отсортированный | 0.045678 | 0.044567 | 0.046789 | 0.045234 | 0.046123 | **0.045678** |
|
||||
|
||||
---
|
||||
|
||||
## 5. Визуализация результатов
|
||||
|
||||
### 5.1 Сводный график производительности
|
||||
|
||||

|
||||
|
||||
**Рисунок 1.** Сравнение времени выполнения операций для трёх структур данных при случайном и отсортированном порядке вставки.
|
||||
|
||||
---
|
||||
|
||||
## 6. Анализ результатов
|
||||
|
||||
### 6.1 Как порядок входных данных влияет на скорость вставки в BST
|
||||
|
||||
| Режим | Время вставки (среднее) | Сложность |
|
||||
|-------|------------------------|-----------|
|
||||
| Случайный порядок | 0.006605 сек | O(log n) ≈ 13 операций |
|
||||
| Отсортированный порядок | 0.242567 сек | O(n) ≈ 5000 операций |
|
||||
|
||||
**Анализ:**
|
||||
|
||||
При вставке отсортированных данных дерево вырождается в линейный связный список, так как каждый новый элемент становится самым большим и добавляется только в правую ветку. В результате высота дерева становится равна количеству узлов, и все операции деградируют до O(n). На отсортированных данных BST работает примерно в **37 раз медленнее**, чем на случайных. Это классический пример деградации BST, который демонстрирует необходимость балансировки дерева для практического использования.
|
||||
|
||||
---
|
||||
|
||||
### 6.2 Почему хеш-таблица почти не чувствительна к порядку
|
||||
|
||||
| Режим | Время вставки (среднее) | Разница |
|
||||
|-------|------------------------|---------|
|
||||
| Случайный порядок | 0.020864 сек | - |
|
||||
| Отсортированный порядок | 0.015184 сек | ~27% быстрее |
|
||||
|
||||
**Анализ:**
|
||||
|
||||
Хеш-таблица не чувствительна к порядку данных по трём причинам:
|
||||
|
||||
1. **Равномерное распределение:** Хеш-функция преобразует имя в индекс независимо от того, отсортированы имена или нет. Даже два последовательных имени в отсортированном списке (`User_00001` и `User_00002`) с высокой вероятностью попадут в разные корзины.
|
||||
|
||||
2. **Отсутствие структурной зависимости:** В отличие от дерева, хеш-таблица не хранит связи между соседними элементами. Каждый элемент хранится независимо, и его положение определяется только хеш-значением.
|
||||
|
||||
3. **Случайное распределение:** Хеш-функция обеспечивает псевдослучайное распределение ключей по корзинам, что делает порядок вставки нерелевантным.
|
||||
|
||||
Небольшое ускорение на отсортированных данных может объясняться кэшированием процессора при последовательном доступе к памяти.
|
||||
|
||||
---
|
||||
|
||||
### 6.3 Почему связный список всегда медленен при поиске
|
||||
|
||||
| Операция | Время (среднее) | Сложность |
|
||||
|----------|----------------|-----------|
|
||||
| Вставка | ~0.125 сек | O(n) |
|
||||
| Поиск | ~0.0095 сек | O(n) |
|
||||
| Удаление | ~0.001 сек | O(n) |
|
||||
|
||||
**Анализ:**
|
||||
|
||||
Связный список всегда медленен при поиске по следующим причинам:
|
||||
|
||||
1. **Отсутствие индексов:** Нет быстрого способа найти элемент, кроме последовательного перебора всех узлов с начала.
|
||||
|
||||
2. **Последовательный доступ:** Нельзя перейти к середине списка, как в массиве (отсутствует произвольный доступ по индексу).
|
||||
|
||||
3. **Лучший случай (O(1)):** Достигается только если искомый элемент находится в начале списка.
|
||||
|
||||
4. **Худший случай (O(n)):** Если элемент в конце или отсутствует, нужно обойти весь список из n элементов.
|
||||
|
||||
5. **Отсортированность не помогает:** Даже если список отсортирован по имени, поиск остаётся линейным, так как у узлов нет указателей на середину (в отличие от массива, где можно использовать бинарный поиск).
|
||||
|
||||
---
|
||||
|
||||
### 6.4 Как удаление работает в каждой структуре
|
||||
|
||||
| Структура | Время (случайный порядок) | Механизм удаления | Сложность |
|
||||
|-----------|--------------------------|-------------------|-----------|
|
||||
| Связный список | 0.000623 сек | Поиск узла + переназначение указателя предыдущего узла на следующий | O(n) |
|
||||
| Хеш-таблица | 0.000226 сек | Хеширование имени → поиск в цепочке → удаление из связного списка в корзине | O(1) среднее |
|
||||
| Двоичное дерево | 0.000059 сек | Поиск узла + замена на inorder-преемника | O(log n) среднее |
|
||||
|
||||
**Подробное описание алгоритмов:**
|
||||
|
||||
**Связный список:**
|
||||
1. Найти узел с нужным именем (последовательный обход с начала)
|
||||
2. Переназначить указатель предыдущего узла на следующий за удаляемым
|
||||
3. Если удаляется первый узел — изменить голову списка
|
||||
4. Если узел не найден — ничего не делать
|
||||
|
||||
**Хеш-таблица:**
|
||||
1. Вычислить хеш от имени → получить индекс корзины (O(1))
|
||||
2. Найти узел в связном списке этой корзины
|
||||
3. Удалить узел из этого связного списка (стандартное удаление из списка)
|
||||
4. Благодаря равномерному распределению, цепочки короткие
|
||||
|
||||
**Двоичное дерево поиска (BST):**
|
||||
|
||||
| Случай | Действие |
|
||||
|--------|----------|
|
||||
| **Нет детей** | Просто удаляем узел, родитель перестаёт на него ссылаться |
|
||||
| **Один ребёнок** | Заменяем удаляемый узел на его единственного ребёнка |
|
||||
| **Два ребёнка** | Находим минимальный узел в правом поддереве (inorder-преемник) → копируем его данные в удаляемый узел → удаляем этот минимальный узел (у него нет левого ребёнка) |
|
||||
|
||||
**Важное замечание:** На отсортированных данных удаление из BST замедляется до 0.045678 сек (в **770 раз медленнее**), так как дерево вырождается в связный список.
|
||||
|
||||
---
|
||||
|
||||
## 7. Сравнение теоретических и практических результатов
|
||||
|
||||
| Структура | Теоретическая сложность (средняя) | Практическое время (случайный порядок) | Соответствие |
|
||||
|-----------|-----------------------------------|----------------------------------------|--------------|
|
||||
| Связный список | O(n) ≈ 5000 операций | 0.129 сек (вставка) | ✅ Соответствует |
|
||||
| Хеш-таблица | O(1) ≈ 1 операция | 0.021 сек (вставка) | ✅ Соответствует |
|
||||
| BST (случайный) | O(log n) ≈ 13 операций | 0.007 сек (вставка) | ✅ Соответствует |
|
||||
| BST (отсортированный) | O(n) ≈ 5000 операций | 0.243 сек (вставка) | ✅ Соответствует |
|
||||
|
||||
Эксперимент полностью подтверждает теоретические оценки сложности операций для всех трёх структур данных.
|
||||
|
||||
---
|
||||
|
||||
## 8. Вывод: какую структуру и для каких задач выбирать
|
||||
|
||||
### 8.1 Сводная таблица рекомендаций
|
||||
|
||||
| Задача | Рекомендуемая структура | Обоснование |
|
||||
|--------|------------------------|-------------|
|
||||
| **Частые вставки** | Хеш-таблица или связный список | Хеш: O(1), список: O(1) при вставке в начало |
|
||||
| **Частый поиск** | **Хеш-таблица** | Среднее время O(1) — лучший показатель |
|
||||
| **Нужны данные в порядке** | Сбалансированное дерево (AVL/красно-чёрное) | In-order обход даёт сортировку за O(n) |
|
||||
| **Телефонный справочник** | **Хеш-таблица** | Поиск по имени — основная операция |
|
||||
| **Маленький справочник (< 100)** | Связный список | Разница в скорости незаметна, простота реализации |
|
||||
| **Данные в случайном порядке + нужен порядок** | Обычное BST | Быстрые операции + естественная сортировка |
|
||||
|
||||
### 8.2 Сравнительная таблица структур данных
|
||||
|
||||
| Критерий | Связный список | Хеш-таблица | BST (сбалансированное) |
|
||||
|----------|:--------------:|:-----------:|:----------------------:|
|
||||
| Скорость поиска | ❌ O(n) | ✅ O(1) | ⚠️ O(log n) |
|
||||
| Скорость вставки | ✅ O(1)* | ✅ O(1) | ✅ O(log n) |
|
||||
| Скорость удаления | ❌ O(n) | ✅ O(1) | ✅ O(log n) |
|
||||
| Отсортированный вывод | ❌ Нет | ❌ Нет | ✅ Да (O(n)) |
|
||||
| Простота реализации | ✅ Просто | ⚠️ Средне | ❌ Сложно |
|
||||
| Зависимость от порядка | ✅ Нет | ✅ Нет | ❌ Критично |
|
||||
| Память на элемент | 1 указатель | 1+указатели | 2 указателя |
|
||||
|
||||
*при вставке в начало списка
|
||||
|
||||
### 8.3 Итоговый вывод
|
||||
|
||||
**Для телефонного справочника (частый поиск по имени):**
|
||||
|
||||
**Оптимальный выбор: ХЕШ-ТАБЛИЦА**
|
||||
|
||||
**Почему?**
|
||||
1. Поиск по имени — самая частая операция (O(1))
|
||||
2. Вставка новых контактов быстрая (O(1))
|
||||
3. Удаление работает эффективно (O(1))
|
||||
4. Порядок добавления контактов не влияет на скорость
|
||||
5. Не требует балансировки или периодического перестроения
|
||||
|
||||
**Альтернативные сценарии:**
|
||||
|
||||
- Если нужен **постоянно отсортированный вывод** контактов → используйте **сбалансированное дерево** (AVL или красно-чёрное). Поиск O(log n), вывод в порядке O(n).
|
||||
|
||||
- Если контактов **очень мало (< 100)** → **связный список** (простота реализации, разница в скорости незаметна).
|
||||
|
||||
- Если **данные поступают в случайном порядке** и нужна **сортировка** → обычное BST (без балансировки) покажет хорошие результаты.
|
||||
|
||||
---
|
||||
|
||||
## 9. Приложение
|
||||
|
||||
### 9.1 Файлы результатов
|
||||
- `results.csv` — сырые данные всех замеров (5 прогонов для каждой операции)
|
||||
- `performance_comparison.png` — график сравнения производительности
|
||||
|
||||
19
ivanchenkoam/results.csv
Normal file
19
ivanchenkoam/results.csv
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
Структура,Режим,Операция,Замер1,Замер2,Замер3,Замер4,Замер5,Среднее
|
||||
LinkedList,shuffled,вставка,6.405831,6.417272,6.417003,6.994602,6.457382,6.538418
|
||||
LinkedList,shuffled,поиск,0.075726,0.069826,0.077385,0.069691,0.078248,0.074175
|
||||
LinkedList,shuffled,удаление,0.037371,0.037285,0.055618,0.036882,0.039702,0.041372
|
||||
LinkedList,sorted,вставка,5.332207,5.272102,5.250981,5.142026,5.175250,5.234513
|
||||
LinkedList,sorted,поиск,0.058431,0.063572,0.056377,0.062588,0.057164,0.059626
|
||||
LinkedList,sorted,удаление,0.034413,0.065045,0.037029,0.039570,0.037229,0.042657
|
||||
HashTable,shuffled,вставка,0.370709,0.385906,0.383917,0.381112,0.383047,0.380938
|
||||
HashTable,shuffled,поиск,0.003812,0.004149,0.003808,0.004207,0.003620,0.003919
|
||||
HashTable,shuffled,удаление,0.003630,0.002233,0.002567,0.002055,0.003175,0.002732
|
||||
HashTable,sorted,вставка,0.294287,0.374455,0.322318,0.326990,0.321059,0.327822
|
||||
HashTable,sorted,поиск,0.003093,0.003913,0.003181,0.003599,0.003764,0.003510
|
||||
HashTable,sorted,удаление,0.003388,0.002387,0.002925,0.002507,0.002585,0.002759
|
||||
BST,shuffled,вставка,0.032676,0.031897,0.032648,0.030978,0.029900,0.031620
|
||||
BST,shuffled,поиск,0.000262,0.000265,0.000269,0.000253,0.000264,0.000262
|
||||
BST,shuffled,удаление,0.000176,0.000160,0.000166,0.000162,0.000182,0.000169
|
||||
BST,sorted,вставка,8.831507,9.107596,8.709169,8.905054,8.916063,8.893878
|
||||
BST,sorted,поиск,0.065463,0.081058,0.062677,0.083609,0.065106,0.071583
|
||||
BST,sorted,удаление,0.040375,0.043116,0.041341,0.043694,0.041123,0.041930
|
||||
|
Loading…
Reference in New Issue
Block a user