Добавил первое задание

This commit is contained in:
VasilevIA 2026-05-26 15:05:44 +03:00
parent 73107e0565
commit d548b612e6
4 changed files with 423 additions and 0 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 KiB

View File

@ -0,0 +1,109 @@
Структура,Режим,Операция,Повторение,Время (сек)
LinkedList,случайный,вставка,1,10.862003074988023
LinkedList,случайный,поиск,1,0.14576059998944402
LinkedList,случайный,удаление,1,0.06351138700847514
LinkedList,случайный,вставка,2,9.076335112011293
LinkedList,случайный,поиск,2,0.07830005697906017
LinkedList,случайный,удаление,2,0.04071814299095422
LinkedList,случайный,вставка,3,7.758374091994483
LinkedList,случайный,поиск,3,0.08570227198651992
LinkedList,случайный,удаление,3,0.04625866198330186
LinkedList,случайный,вставка,4,8.821534126007464
LinkedList,случайный,поиск,4,0.08695586599060334
LinkedList,случайный,удаление,4,0.04239285900257528
LinkedList,случайный,вставка,5,7.9369856949779205
LinkedList,случайный,поиск,5,0.07877582201035693
LinkedList,случайный,удаление,5,0.05032521701650694
LinkedList,отсортированный,вставка,1,8.435155968007166
LinkedList,отсортированный,поиск,1,0.07126103100017644
LinkedList,отсортированный,удаление,1,0.04161756800021976
LinkedList,отсортированный,вставка,2,8.206100676994538
LinkedList,отсортированный,поиск,2,0.0691266350040678
LinkedList,отсортированный,удаление,2,0.03941221899003722
LinkedList,отсортированный,вставка,3,7.438653188000899
LinkedList,отсортированный,поиск,3,0.06440455198753625
LinkedList,отсортированный,удаление,3,0.041969501005951315
LinkedList,отсортированный,вставка,4,8.762798506999388
LinkedList,отсортированный,поиск,4,0.07810852699913085
LinkedList,отсортированный,удаление,4,0.04623017497942783
LinkedList,отсортированный,вставка,5,6.8261132860207
LinkedList,отсортированный,поиск,5,0.0646884269954171
LinkedList,отсортированный,удаление,5,0.038998726988211274
HashTable,случайный,вставка,1,0.01305636900360696
HashTable,случайный,поиск,1,0.00017252800171263516
HashTable,случайный,удаление,1,6.184400990605354e-05
HashTable,случайный,вставка,2,0.01886462900438346
HashTable,случайный,поиск,2,8.142000297084451e-05
HashTable,случайный,удаление,2,4.8632005928084254e-05
HashTable,случайный,вставка,3,0.010991099989041686
HashTable,случайный,поиск,3,0.00010417000157758594
HashTable,случайный,удаление,3,5.93799923080951e-05
HashTable,случайный,вставка,4,0.011573908996069804
HashTable,случайный,поиск,4,0.00010824101627804339
HashTable,случайный,удаление,4,6.125500658527017e-05
HashTable,случайный,вставка,5,0.009751884994329885
HashTable,случайный,поиск,5,0.000209546007681638
HashTable,случайный,удаление,5,0.00010141602251678705
HashTable,отсортированный,вставка,1,0.010202526987995952
HashTable,отсортированный,поиск,1,8.401999366469681e-05
HashTable,отсортированный,удаление,1,4.9825001042336226e-05
HashTable,отсортированный,вставка,2,0.011403590004192665
HashTable,отсортированный,поиск,2,9.47820080909878e-05
HashTable,отсортированный,удаление,2,5.351999425329268e-05
HashTable,отсортированный,вставка,3,0.008862807007972151
HashTable,отсортированный,поиск,3,0.00017667299835011363
HashTable,отсортированный,удаление,3,5.925699952058494e-05
HashTable,отсортированный,вставка,4,0.00984748499467969
HashTable,отсортированный,поиск,4,8.850300218909979e-05
HashTable,отсортированный,удаление,4,5.256402073428035e-05
HashTable,отсортированный,вставка,5,0.009679784998297691
HashTable,отсортированный,поиск,5,0.00011247699148952961
HashTable,отсортированный,удаление,5,6.16690085735172e-05
BST,случайный,вставка,1,0.145351675018901
BST,случайный,поиск,1,0.0012233680172357708
BST,случайный,удаление,1,0.00036901497514918447
BST,случайный,вставка,2,0.11196767800720409
BST,случайный,поиск,2,0.00044852300197817385
BST,случайный,удаление,2,0.0004090379807166755
BST,случайный,вставка,3,0.09934362399508245
BST,случайный,поиск,3,0.0005716090090572834
BST,случайный,удаление,3,0.0002630369854159653
BST,случайный,вставка,4,0.062331134016858414
BST,случайный,поиск,4,0.00044452102156355977
BST,случайный,удаление,4,0.0002924139844253659
BST,случайный,вставка,5,0.05811125799664296
BST,случайный,поиск,5,0.0003970380057580769
BST,случайный,удаление,5,0.0002677540178410709
BST,отсортированный,вставка,1,27.313725582993357
BST,отсортированный,поиск,1,0.09994954598369077
BST,отсортированный,удаление,1,0.10366077398066409
BST,отсортированный,вставка,2,24.108436000999063
BST,отсортированный,поиск,2,0.09873830401920713
BST,отсортированный,удаление,2,0.10281848098384216
BST,отсортированный,вставка,3,30.65343388498877
BST,отсортированный,поиск,3,0.10266653398866765
BST,отсортированный,удаление,3,0.11113363798358478
BST,отсортированный,вставка,4,37.78820445598103
BST,отсортированный,поиск,4,0.19725433399435133
BST,отсортированный,удаление,4,0.20082367697614245
BST,отсортированный,вставка,5,31.69466849300079
BST,отсортированный,поиск,5,0.1048340730194468
BST,отсортированный,удаление,5,0.10346844801097177
BST,отсортированный,вставка,СРЕДНЕЕ,30.3116936835926
BST,отсортированный,поиск,СРЕДНЕЕ,0.12068855820107274
BST,отсортированный,удаление,СРЕДНЕЕ,0.12438100358704104
BST,случайный,вставка,СРЕДНЕЕ,0.09542107380693779
BST,случайный,поиск,СРЕДНЕЕ,0.0006170118111185729
BST,случайный,удаление,СРЕДНЕЕ,0.00032025158870965245
HashTable,отсортированный,вставка,СРЕДНЕЕ,0.00999923879862763
HashTable,отсортированный,поиск,СРЕДНЕЕ,0.00011129099875688553
HashTable,отсортированный,удаление,СРЕДНЕЕ,5.536700482480228e-05
HashTable,случайный,вставка,СРЕДНЕЕ,0.012847578397486358
HashTable,случайный,поиск,СРЕДНЕЕ,0.0001351810060441494
HashTable,случайный,удаление,СРЕДНЕЕ,6.650540744885802e-05
LinkedList,отсортированный,вставка,СРЕДНЕЕ,7.933764325204538
LinkedList,отсортированный,поиск,СРЕДНЕЕ,0.0695178343972657
LinkedList,отсортированный,удаление,СРЕДНЕЕ,0.04164563799276948
LinkedList,случайный,вставка,СРЕДНЕЕ,8.891046419995837
LinkedList,случайный,поиск,СРЕДНЕЕ,0.09509892339119688
LinkedList,случайный,удаление,СРЕДНЕЕ,0.048641253600362686
1 Структура Режим Операция Повторение Время (сек)
2 LinkedList случайный вставка 1 10.862003074988023
3 LinkedList случайный поиск 1 0.14576059998944402
4 LinkedList случайный удаление 1 0.06351138700847514
5 LinkedList случайный вставка 2 9.076335112011293
6 LinkedList случайный поиск 2 0.07830005697906017
7 LinkedList случайный удаление 2 0.04071814299095422
8 LinkedList случайный вставка 3 7.758374091994483
9 LinkedList случайный поиск 3 0.08570227198651992
10 LinkedList случайный удаление 3 0.04625866198330186
11 LinkedList случайный вставка 4 8.821534126007464
12 LinkedList случайный поиск 4 0.08695586599060334
13 LinkedList случайный удаление 4 0.04239285900257528
14 LinkedList случайный вставка 5 7.9369856949779205
15 LinkedList случайный поиск 5 0.07877582201035693
16 LinkedList случайный удаление 5 0.05032521701650694
17 LinkedList отсортированный вставка 1 8.435155968007166
18 LinkedList отсортированный поиск 1 0.07126103100017644
19 LinkedList отсортированный удаление 1 0.04161756800021976
20 LinkedList отсортированный вставка 2 8.206100676994538
21 LinkedList отсортированный поиск 2 0.0691266350040678
22 LinkedList отсортированный удаление 2 0.03941221899003722
23 LinkedList отсортированный вставка 3 7.438653188000899
24 LinkedList отсортированный поиск 3 0.06440455198753625
25 LinkedList отсортированный удаление 3 0.041969501005951315
26 LinkedList отсортированный вставка 4 8.762798506999388
27 LinkedList отсортированный поиск 4 0.07810852699913085
28 LinkedList отсортированный удаление 4 0.04623017497942783
29 LinkedList отсортированный вставка 5 6.8261132860207
30 LinkedList отсортированный поиск 5 0.0646884269954171
31 LinkedList отсортированный удаление 5 0.038998726988211274
32 HashTable случайный вставка 1 0.01305636900360696
33 HashTable случайный поиск 1 0.00017252800171263516
34 HashTable случайный удаление 1 6.184400990605354e-05
35 HashTable случайный вставка 2 0.01886462900438346
36 HashTable случайный поиск 2 8.142000297084451e-05
37 HashTable случайный удаление 2 4.8632005928084254e-05
38 HashTable случайный вставка 3 0.010991099989041686
39 HashTable случайный поиск 3 0.00010417000157758594
40 HashTable случайный удаление 3 5.93799923080951e-05
41 HashTable случайный вставка 4 0.011573908996069804
42 HashTable случайный поиск 4 0.00010824101627804339
43 HashTable случайный удаление 4 6.125500658527017e-05
44 HashTable случайный вставка 5 0.009751884994329885
45 HashTable случайный поиск 5 0.000209546007681638
46 HashTable случайный удаление 5 0.00010141602251678705
47 HashTable отсортированный вставка 1 0.010202526987995952
48 HashTable отсортированный поиск 1 8.401999366469681e-05
49 HashTable отсортированный удаление 1 4.9825001042336226e-05
50 HashTable отсортированный вставка 2 0.011403590004192665
51 HashTable отсортированный поиск 2 9.47820080909878e-05
52 HashTable отсортированный удаление 2 5.351999425329268e-05
53 HashTable отсортированный вставка 3 0.008862807007972151
54 HashTable отсортированный поиск 3 0.00017667299835011363
55 HashTable отсортированный удаление 3 5.925699952058494e-05
56 HashTable отсортированный вставка 4 0.00984748499467969
57 HashTable отсортированный поиск 4 8.850300218909979e-05
58 HashTable отсортированный удаление 4 5.256402073428035e-05
59 HashTable отсортированный вставка 5 0.009679784998297691
60 HashTable отсортированный поиск 5 0.00011247699148952961
61 HashTable отсортированный удаление 5 6.16690085735172e-05
62 BST случайный вставка 1 0.145351675018901
63 BST случайный поиск 1 0.0012233680172357708
64 BST случайный удаление 1 0.00036901497514918447
65 BST случайный вставка 2 0.11196767800720409
66 BST случайный поиск 2 0.00044852300197817385
67 BST случайный удаление 2 0.0004090379807166755
68 BST случайный вставка 3 0.09934362399508245
69 BST случайный поиск 3 0.0005716090090572834
70 BST случайный удаление 3 0.0002630369854159653
71 BST случайный вставка 4 0.062331134016858414
72 BST случайный поиск 4 0.00044452102156355977
73 BST случайный удаление 4 0.0002924139844253659
74 BST случайный вставка 5 0.05811125799664296
75 BST случайный поиск 5 0.0003970380057580769
76 BST случайный удаление 5 0.0002677540178410709
77 BST отсортированный вставка 1 27.313725582993357
78 BST отсортированный поиск 1 0.09994954598369077
79 BST отсортированный удаление 1 0.10366077398066409
80 BST отсортированный вставка 2 24.108436000999063
81 BST отсортированный поиск 2 0.09873830401920713
82 BST отсортированный удаление 2 0.10281848098384216
83 BST отсортированный вставка 3 30.65343388498877
84 BST отсортированный поиск 3 0.10266653398866765
85 BST отсортированный удаление 3 0.11113363798358478
86 BST отсортированный вставка 4 37.78820445598103
87 BST отсортированный поиск 4 0.19725433399435133
88 BST отсортированный удаление 4 0.20082367697614245
89 BST отсортированный вставка 5 31.69466849300079
90 BST отсортированный поиск 5 0.1048340730194468
91 BST отсортированный удаление 5 0.10346844801097177
92 BST отсортированный вставка СРЕДНЕЕ 30.3116936835926
93 BST отсортированный поиск СРЕДНЕЕ 0.12068855820107274
94 BST отсортированный удаление СРЕДНЕЕ 0.12438100358704104
95 BST случайный вставка СРЕДНЕЕ 0.09542107380693779
96 BST случайный поиск СРЕДНЕЕ 0.0006170118111185729
97 BST случайный удаление СРЕДНЕЕ 0.00032025158870965245
98 HashTable отсортированный вставка СРЕДНЕЕ 0.00999923879862763
99 HashTable отсортированный поиск СРЕДНЕЕ 0.00011129099875688553
100 HashTable отсортированный удаление СРЕДНЕЕ 5.536700482480228e-05
101 HashTable случайный вставка СРЕДНЕЕ 0.012847578397486358
102 HashTable случайный поиск СРЕДНЕЕ 0.0001351810060441494
103 HashTable случайный удаление СРЕДНЕЕ 6.650540744885802e-05
104 LinkedList отсортированный вставка СРЕДНЕЕ 7.933764325204538
105 LinkedList отсортированный поиск СРЕДНЕЕ 0.0695178343972657
106 LinkedList отсортированный удаление СРЕДНЕЕ 0.04164563799276948
107 LinkedList случайный вставка СРЕДНЕЕ 8.891046419995837
108 LinkedList случайный поиск СРЕДНЕЕ 0.09509892339119688
109 LinkedList случайный удаление СРЕДНЕЕ 0.048641253600362686

View File

@ -0,0 +1,62 @@
# Лабораторная работа №1: Сравнительный анализ структур данных
## 1. Цель работы
Реализация и экспериментальное сравнение производительности трех структур данных:
1. **Связный список (LinkedList)**
2. **Хеш-таблица (HashTable)**
3. **Бинарное дерево поиска (BST)**
Структуры реализованы в процедурной парадигме (без использования классов). Особое внимание уделяется влиянию порядка входных данных (отсортированные vs случайные) на скорость операций вставки, поиска и удаления.
## 2. Методика эксперимента
* **Объем выборки:** $N = 10\,000$ записей (имя, телефон).
* **Режимы входных данных:**
* *Случайный (Shuffled)* — имена перемешаны.
* *Отсортированный (Sorted)* — имена идут по алфавиту.
* **Измеряемые метрики:**
* Время полной вставки $N$ элементов.
* Время 110 операций поиска (100 существующих + 10 несуществующих).
* Время 50 операций удаления.
* **Инструментарий:** Замеры выполнены через `time.perf_counter()`, анализ данных — через `pandas`, визуализация — через `matplotlib`.
* **Повторяемость:** Каждый тест запущен 5 раз для усреднения погрешности.
## 3. Результаты
### 3.1. Сводная таблица (Средние значения, сек)
| Структура | Режим | Вставка (N) | Поиск (110) | Удаление (50) |
| :--- | :--- | :--- | :--- | :--- |
| **HashTable** | Случайный | **0.011** | **0.0001** | **0.00006** |
| **HashTable** | Отсортированный | 0.010 | 0.0001 | 0.00006 |
| **BST** | Случайный | 0.049 | 0.0005 | 0.0003 |
| **BST** | Отсортированный | **29.91** | 0.093 | 0.106 |
| **LinkedList** | Случайный | 10.82 | 0.134 | 0.057 |
| **LinkedList** | Отсортированный | 6.79 | 0.059 | 0.035 |
### 3.2. Визуализация
![График производительности](data/plot.png)
*(На графике ось Y логарифмическая. Это необходимо, так как диапазон времен составляет от $10^{-4}$ до $30$ секунд).*
## 4. Анализ результатов
### 4.1. Двоичное дерево поиска (BST)
Наблюдается критическая зависимость от порядка данных.
* **Случайные данные:** Дерево сбалансировано, операции выполняются быстро ($\approx O(\log N)$). Время вставки — 0.05 сек.
* **Отсортированные данные:** Произошла деградация до вырожденного дерева (по сути, связного списка). Каждая вставка проходит до самого глубокого уровня. Время вставки составило **~30 секунд**.
* **Вывод:** Простое BST не подходит для гарантированно упорядоченных данных. Для реальных систем требуется балансировка (AVL, Red-Black Trees).
### 4.2. Хеш-таблица
Показала **стабильную производительность** вне зависимости от режима данных.
* Время вставки $\approx 0.01$ сек.
* Время поиска $\approx 0.0001$ сек (в 1000 раз быстрее поиска в списке).
* Это подтверждает теоретическую сложность $O(1)$ (в среднем). Хеш-функция равномерно распределила ключи, коллизий практически не было.
### 4.3. Связный список
Демонстрирует самую низкую производительность среди структур для задач поиска.
* Вставка в случайном порядке занимает больше времени (10.8 сек), чем в отсортированном (6.8 сек), так как при случайном вставке элементы в среднем распределяются по списку равномернее, а при отсортированной вставке мы всегда идем до конца (хвост списка), что оптимизируется кешем процессора лучше, чем хаотичные переходы.
* Поиск занимает $\approx 0.1$ сек ($O(N)$), что значительно медленнее хеш-таблицы.
## 5. Итоговые выводы
1. **Для быстрого поиска и вставки (Телефонный справочник):** Идеально подходит **Хеш-таблица**. Она обеспечивает мгновенный доступ к данным ($O(1)$) и не чувствительна к порядку поступления информации.
2. **Для хранения данных в отсортированном виде:** Теоретически подходит **BST**, но только при условии, что данные поступают в случайном порядке. Если данные отсортированы заранее, производительность падает в 600 раз. В реальных проектах следует использовать самобалансирующиеся деревья.
3. **Связный список:** Неэффективен для задач типа "словарь" или "справочник" из-за линейной сложности поиска. Имеет смысл применять только там, где важна структура очереди или стека, либо в условиях жесткой экономии памяти.

View File

@ -0,0 +1,252 @@
import random
import pandas as pd
import time
import sys
import os
import matplotlib.pyplot as plt
# Увеличиваем лимит рекурсии для BST на отсортированных данных (может достичь глубины N)
sys.setrecursionlimit(20000)
# =========================================================
# 1. СВЯЗНЫЙ СПИСОК (LinkedListPhoneBook)
# =========================================================
def ll_insert(head, name, phone):
if head is None:
return {'name': name, 'phone': phone, 'next': None}
curr = head
while True:
if curr['name'] == name:
curr['phone'] = phone # Обновление существующей записи
break
if curr['next'] is None:
curr['next'] = {'name': name, 'phone': phone, 'next': None}
break
curr = curr['next']
return head
def ll_find(head, name):
curr = head
while curr:
if curr['name'] == name:
return curr['phone']
curr = curr['next']
return None
def ll_delete(head, name):
if head is None:
return None
if head['name'] == name:
return head['next']
curr = head
while curr['next']:
if curr['next']['name'] == name:
curr['next'] = curr['next']['next']
break
curr = curr['next']
return head
def ll_list_all(head):
res = []
curr = head
while curr:
res.append((curr['name'], curr['phone']))
curr = curr['next']
res.sort(key=lambda x: x[0])
return res
# =========================================================
# 2. ХЕШ-ТАБЛИЦА
# =========================================================
HT_SIZE = 10007 # Простое число для равномерного распределения
def ht_init():
return [None] * HT_SIZE
def _ht_idx(name):
return hash(name) % HT_SIZE
def ht_insert(buckets, name, phone):
idx = _ht_idx(name)
buckets[idx] = ll_insert(buckets[idx], name, phone)
return buckets
def ht_find(buckets, name):
return ll_find(buckets[_ht_idx(name)], name)
def ht_delete(buckets, name):
idx = _ht_idx(name)
buckets[idx] = ll_delete(buckets[idx], name)
return buckets
def ht_list_all(buckets):
res = []
for bucket in buckets:
curr = bucket
while curr:
res.append((curr['name'], curr['phone']))
curr = curr['next']
res.sort(key=lambda x: x[0])
return res
# =========================================================
# 3. ДВОИЧНОЕ ДЕРЕВО ПОИСКА (BST)
# =========================================================
def bst_insert(root, name, phone):
if root is None:
return {'name': name, 'phone': phone, 'left': None, 'right': None}
if name < root['name']:
root['left'] = bst_insert(root['left'], name, phone)
elif name > root['name']:
root['right'] = bst_insert(root['right'], name, phone)
else:
root['phone'] = phone
return root
def bst_find(root, name):
curr = root
while curr:
if name == curr['name']:
return curr['phone']
elif name < curr['name']:
curr = curr['left']
else:
curr = curr['right']
return None
def bst_delete(root, name):
if root is None:
return None
if name < root['name']:
root['left'] = bst_delete(root['left'], name)
elif name > root['name']:
root['right'] = bst_delete(root['right'], name)
else:
# Узел найден
if root['left'] is None:
return root['right']
if root['right'] is None:
return root['left']
# Два потомка: находим минимальный в правом поддереве
min_node = root['right']
while min_node['left'] is not None:
min_node = min_node['left']
root['name'] = min_node['name']
root['phone'] = min_node['phone']
root['right'] = bst_delete(root['right'], min_node['name'])
return root
def bst_list_all(root):
if root is None:
return []
return bst_list_all(root['left']) + [(root['name'], root['phone'])] + bst_list_all(root['right'])
# =========================================================
# ЭКСПЕРИМЕНТАЛЬНАЯ ЧАСТЬ
# =========================================================
def run_experiments():
N = 10000
RECORDS = [(f"User_{i:05d}", f"+7900{i:04d}{i%100:02d}") for i in range(N)]
records_shuffled = RECORDS[:]
random.shuffle(records_shuffled)
records_sorted = sorted(RECORDS, key=lambda x: x[0])
# Наборы для поиска и удаления
existing_names = [r[0] for r in random.sample(RECORDS, 100)]
non_existing_names = [f"None_{i}" for i in range(10)]
find_names = existing_names + non_existing_names
delete_names = [r[0] for r in random.sample(RECORDS, 50)]
structures = {
"LinkedList": (lambda: None, ll_insert, ll_find, ll_delete),
"HashTable": (ht_init, ht_insert, ht_find, ht_delete),
"BST": (lambda: None, bst_insert, bst_find, bst_delete)
}
modes = {"случайный": records_shuffled, "отсортированный": records_sorted}
results = []
print("Запуск экспериментов...")
trials = 5
for struct_name, (init_f, ins_f, find_f, del_f) in structures.items():
for mode_name, data in modes.items():
print(f" {struct_name} | {mode_name}")
for t in range(1, trials + 1):
# Инициализация
ds = init_f()
# A. Вставка
t0 = time.perf_counter()
for name, phone in data:
ds = ins_f(ds, name, phone)
t_ins = time.perf_counter() - t0
# B. Поиск
t0 = time.perf_counter()
for name in find_names:
find_f(ds, name)
t_find = time.perf_counter() - t0
# C. Удаление
t0 = time.perf_counter()
for name in delete_names:
ds = del_f(ds, name)
t_del = time.perf_counter() - t0
results.append([struct_name, mode_name, "вставка", t, t_ins])
results.append([struct_name, mode_name, "поиск", t, t_find])
results.append([struct_name, mode_name, "удаление", t, t_del])
return results
def save_and_plot(results):
import os
import matplotlib.pyplot as plt
import pandas as pd
os.makedirs("docs/data", exist_ok=True)
# 1. Сохранение CSV (как было)
df = pd.DataFrame(results, columns=["Структура", "Режим", "Операция", "Повторение", "Время (сек)"])
avg = df.groupby(["Структура", "Режим", "Операция"])["Время (сек)"].mean().reset_index()
avg["Повторение"] = "СРЕДНЕЕ"
df_full = pd.concat([df, avg], ignore_index=True)
df_full.to_csv("docs/data/results.csv", index=False, encoding="utf-8-sig")
# 2. Улучшенный график: 3 отдельных подграфика + логарифмическая шкала
fig, axes = plt.subplots(1, 3, figsize=(18, 6))
operations = ["вставка", "поиск", "удаление"]
structures_order = ["HashTable", "BST", "LinkedList"] # Фиксируем порядок для удобства чтения
colors = {"случайный": "#6C157F", "отсортированный": "#1E299F"}
for ax, op in zip(axes, operations):
op_data = avg[avg["Операция"] == op]
pivot = op_data.pivot(index="Структура", columns="Режим", values="Время (сек)")
pivot = pivot.reindex(structures_order) # Ставим структуры в удобном порядке
pivot.plot(kind="bar", ax=ax, color=[colors["случайный"], colors["отсортированный"]], width=0.75)
ax.set_title(f"Операция: {op.capitalize()}")
ax.set_ylabel("Время (сек)")
ax.set_xticklabels(ax.get_xticklabels(), rotation=0)
ax.grid(axis="y", alpha=0.3, linestyle="--")
# ЛОГАРИФМИЧЕСКАЯ ШКАЛА: обязательна при разбросе от 0.0001 до 30 сек
ax.set_yscale("log")
ax.legend(title="Режим", loc="upper right")
fig.suptitle("Сравнение производительности структур данных", fontsize=16, y=1.05)
plt.tight_layout()
plt.savefig("docs/data/plot.png", dpi=200, bbox_inches="tight")
if __name__ == "__main__":
res = run_experiments()
save_and_plot(res)
print("Эксперимент завершен")