[1] исправлено проведение замеров и отчет
This commit is contained in:
parent
579df4fff2
commit
9800ba7078
|
|
@ -8,8 +8,6 @@ from bst_phonebook import *
|
||||||
|
|
||||||
sys.setrecursionlimit(100000)
|
sys.setrecursionlimit(100000)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def generate_test_data(n=10000):
|
def generate_test_data(n=10000):
|
||||||
"""Генерация тестовых данных"""
|
"""Генерация тестовых данных"""
|
||||||
uniform_records = [(f"User_{i:05d}", f"+7-999-{i:07d}") for i in range(n)]
|
uniform_records = [(f"User_{i:05d}", f"+7-999-{i:07d}") for i in range(n)]
|
||||||
|
|
@ -50,83 +48,96 @@ def run_benchmarks():
|
||||||
('отсортированный', test_data['sorted'])
|
('отсортированный', test_data['sorted'])
|
||||||
]
|
]
|
||||||
|
|
||||||
|
REPEATS = 5 # Количество повторов
|
||||||
|
|
||||||
for struct_name, struct_type in structures:
|
for struct_name, struct_type in structures:
|
||||||
print(f"\n=== Тестирование {struct_name} ===")
|
print(f"\n=== Тестирование {struct_name} ===")
|
||||||
|
|
||||||
for mode_name, records in modes:
|
for mode_name, records in modes:
|
||||||
print(f" Режим: {mode_name}")
|
print(f" Режим: {mode_name}")
|
||||||
|
|
||||||
# Создаем структуру и меряем вставку
|
# Запускаем 5 повторов для каждой комбинации
|
||||||
if struct_type == 'll':
|
for rep in range(1, REPEATS + 1):
|
||||||
structure = None
|
print(f" Повтор {rep}/{REPEATS}...")
|
||||||
start = time.perf_counter()
|
|
||||||
for name, phone in records:
|
|
||||||
structure = ll_insert(structure, name, phone)
|
|
||||||
end = time.perf_counter()
|
|
||||||
insert_time = end - start
|
|
||||||
|
|
||||||
elif struct_type == 'ht':
|
# Создаем структуру и меряем вставку
|
||||||
structure = create_hash_table(5000)
|
if struct_type == 'll':
|
||||||
start = time.perf_counter()
|
structure = None
|
||||||
for name, phone in records:
|
start = time.perf_counter()
|
||||||
ht_insert(structure, name, phone)
|
for name, phone in records:
|
||||||
end = time.perf_counter()
|
structure = ll_insert(structure, name, phone)
|
||||||
insert_time = end - start
|
end = time.perf_counter()
|
||||||
|
insert_time = end - start
|
||||||
|
|
||||||
|
elif struct_type == 'ht':
|
||||||
|
structure = create_hash_table(5000)
|
||||||
|
start = time.perf_counter()
|
||||||
|
for name, phone in records:
|
||||||
|
ht_insert(structure, name, phone)
|
||||||
|
end = time.perf_counter()
|
||||||
|
insert_time = end - start
|
||||||
|
|
||||||
|
elif struct_type == 'bst':
|
||||||
|
structure = None
|
||||||
|
start = time.perf_counter()
|
||||||
|
for name, phone in records:
|
||||||
|
structure = bst_insert(structure, name, phone)
|
||||||
|
end = time.perf_counter()
|
||||||
|
insert_time = end - start
|
||||||
|
|
||||||
elif struct_type == 'bst':
|
results.append([struct_name, mode_name, "вставка", insert_time, rep])
|
||||||
structure = None
|
|
||||||
|
# Поиск
|
||||||
start = time.perf_counter()
|
start = time.perf_counter()
|
||||||
for name, phone in records:
|
for name in test_data['search_names']:
|
||||||
structure = bst_insert(structure, name, phone)
|
if struct_type == 'll':
|
||||||
|
ll_find(structure, name)
|
||||||
|
elif struct_type == 'ht':
|
||||||
|
ht_find(structure, name)
|
||||||
|
elif struct_type == 'bst':
|
||||||
|
bst_find(structure, name)
|
||||||
end = time.perf_counter()
|
end = time.perf_counter()
|
||||||
insert_time = end - start
|
find_time = end - start
|
||||||
|
results.append([struct_name, mode_name, "поиск", find_time, rep])
|
||||||
print(f" Вставка: {insert_time:.6f} сек")
|
|
||||||
results.append([struct_name, mode_name, "вставка", insert_time])
|
# Удаление
|
||||||
|
start = time.perf_counter()
|
||||||
# Поиск
|
for name in test_data['delete_names']:
|
||||||
start = time.perf_counter()
|
if struct_type == 'll':
|
||||||
for name in test_data['search_names']:
|
structure = ll_delete(structure, name)
|
||||||
if struct_type == 'll':
|
elif struct_type == 'ht':
|
||||||
ll_find(structure, name)
|
ht_delete(structure, name)
|
||||||
elif struct_type == 'ht':
|
elif struct_type == 'bst':
|
||||||
ht_find(structure, name)
|
structure = bst_delete(structure, name)
|
||||||
elif struct_type == 'bst':
|
end = time.perf_counter()
|
||||||
bst_find(structure, name)
|
delete_time = end - start
|
||||||
end = time.perf_counter()
|
results.append([struct_name, mode_name, "удаление", delete_time, rep])
|
||||||
find_time = end - start
|
|
||||||
print(f" Поиск (60 запросов): {find_time:.6f} сек")
|
|
||||||
results.append([struct_name, mode_name, "поиск", find_time])
|
|
||||||
|
|
||||||
# Удаление
|
|
||||||
start = time.perf_counter()
|
|
||||||
for name in test_data['delete_names']:
|
|
||||||
if struct_type == 'll':
|
|
||||||
structure = ll_delete(structure, name)
|
|
||||||
elif struct_type == 'ht':
|
|
||||||
ht_delete(structure, name)
|
|
||||||
elif struct_type == 'bst':
|
|
||||||
structure = bst_delete(structure, name)
|
|
||||||
end = time.perf_counter()
|
|
||||||
delete_time = end - start
|
|
||||||
print(f" Удаление (30 записей): {delete_time:.6f} сек")
|
|
||||||
results.append([struct_name, mode_name, "удаление", delete_time])
|
|
||||||
|
|
||||||
# Сохраняем в CSV
|
# Сохраняем в CSV с колонкой "Повтор"
|
||||||
with open('docs/data/results.csv', 'w', newline='', encoding='utf-8') as f:
|
with open('docs/data/results.csv', 'w', newline='', encoding='utf-8') as f:
|
||||||
writer = csv.writer(f)
|
writer = csv.writer(f)
|
||||||
writer.writerow(['Структура', 'Режим', 'Операция', 'Время (сек)'])
|
writer.writerow(['Структура', 'Режим', 'Операция', 'Время (сек)', 'Повтор'])
|
||||||
writer.writerows(results)
|
writer.writerows(results)
|
||||||
|
|
||||||
print("\n" + "="*60)
|
# Подсчет средних значений
|
||||||
print("ИТОГОВЫЕ РЕЗУЛЬТАТЫ (в секундах)")
|
print("\n" + "="*70)
|
||||||
print("="*60)
|
print("СРЕДНИЕ ЗНАЧЕНИЯ (по 5 повторам)")
|
||||||
print(f"{'Структура':12} {'Режим':12} {'Операция':10} {'Время':>10}")
|
print("="*70)
|
||||||
print("-"*50)
|
|
||||||
for row in results:
|
|
||||||
print(f"{row[0]:12} {row[1]:12} {row[2]:10} {row[3]:10.6f}")
|
|
||||||
|
|
||||||
print(f"\nРезультаты сохранены в docs/data/results.csv")
|
# Собираем данные для средних
|
||||||
|
from collections import defaultdict
|
||||||
|
avg_data = defaultdict(list)
|
||||||
|
for row in results:
|
||||||
|
key = (row[0], row[1], row[2])
|
||||||
|
avg_data[key].append(row[3])
|
||||||
|
|
||||||
|
print(f"{'Структура':15} {'Режим':13} {'Операция':10} {'Среднее время':>12}")
|
||||||
|
print("-"*55)
|
||||||
|
for (struct, mode, op), times in avg_data.items():
|
||||||
|
avg_time = sum(times) / len(times)
|
||||||
|
print(f"{struct:15} {mode:13} {op:10} {avg_time:12.6f}")
|
||||||
|
|
||||||
|
print(f"\nВсе замеры (5 повторов) сохранены в docs/data/results.csv")
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
random.seed(42)
|
random.seed(42)
|
||||||
|
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 86 KiB After Width: | Height: | Size: 89 KiB |
|
|
@ -1,19 +1,91 @@
|
||||||
Структура,Режим,Операция,Время (сек)
|
Структура,Режим,Операция,Время (сек),Повтор
|
||||||
LinkedList,случайный,вставка,6.751254200004041
|
LinkedList,случайный,вставка,4.9375476999994135,1
|
||||||
LinkedList,случайный,поиск,0.07962289988063276
|
LinkedList,случайный,поиск,0.04131099999358412,1
|
||||||
LinkedList,случайный,удаление,0.038067599991336465
|
LinkedList,случайный,удаление,0.02149870000721421,1
|
||||||
LinkedList,отсортированный,вставка,7.378327900078148
|
LinkedList,случайный,вставка,4.644251200006693,2
|
||||||
LinkedList,отсортированный,поиск,0.09230039990507066
|
LinkedList,случайный,поиск,0.042833100000279956,2
|
||||||
LinkedList,отсортированный,удаление,0.023862000089138746
|
LinkedList,случайный,удаление,0.020811700000194833,2
|
||||||
HashTable,случайный,вставка,0.02441199985332787
|
LinkedList,случайный,вставка,4.78751110000303,3
|
||||||
HashTable,случайный,поиск,0.0002272999845445156
|
LinkedList,случайный,поиск,0.041008800006238744,3
|
||||||
HashTable,случайный,удаление,0.00011650007218122482
|
LinkedList,случайный,удаление,0.02328480000142008,3
|
||||||
HashTable,отсортированный,вставка,0.023515600012615323
|
LinkedList,случайный,вставка,5.261260200000834,4
|
||||||
HashTable,отсортированный,поиск,0.00027600000612437725
|
LinkedList,случайный,поиск,0.043706600001314655,4
|
||||||
HashTable,отсортированный,удаление,0.00012340000830590725
|
LinkedList,случайный,удаление,0.022936199995456263,4
|
||||||
BST,случайный,вставка,0.03815519995987415
|
LinkedList,случайный,вставка,4.584412900003372,5
|
||||||
BST,случайный,поиск,0.00031240005046129227
|
LinkedList,случайный,поиск,0.10296139999991283,5
|
||||||
BST,случайный,удаление,0.00018319999799132347
|
LinkedList,случайный,удаление,0.06556309999723453,5
|
||||||
BST,отсортированный,вставка,21.532808099873364
|
LinkedList,отсортированный,вставка,4.5104472000093665,1
|
||||||
BST,отсортированный,поиск,0.18976689991541207
|
LinkedList,отсортированный,поиск,0.03982529998756945,1
|
||||||
BST,отсортированный,удаление,0.07795759988948703
|
LinkedList,отсортированный,удаление,0.016976200000499375,1
|
||||||
|
LinkedList,отсортированный,вставка,4.366683700005524,2
|
||||||
|
LinkedList,отсортированный,поиск,0.06564230000367388,2
|
||||||
|
LinkedList,отсортированный,удаление,0.028787899995222688,2
|
||||||
|
LinkedList,отсортированный,вставка,4.719926499994472,3
|
||||||
|
LinkedList,отсортированный,поиск,0.04211149999173358,3
|
||||||
|
LinkedList,отсортированный,удаление,0.01897859999735374,3
|
||||||
|
LinkedList,отсортированный,вставка,4.7542686000088,4
|
||||||
|
LinkedList,отсортированный,поиск,0.036636300006648526,4
|
||||||
|
LinkedList,отсортированный,удаление,0.018097999985911883,4
|
||||||
|
LinkedList,отсортированный,вставка,4.634292700007791,5
|
||||||
|
LinkedList,отсортированный,поиск,0.038695100010954775,5
|
||||||
|
LinkedList,отсортированный,удаление,0.0167280000023311,5
|
||||||
|
HashTable,случайный,вставка,0.02125880001403857,1
|
||||||
|
HashTable,случайный,поиск,0.0002066000015474856,1
|
||||||
|
HashTable,случайный,удаление,0.0001053000014508143,1
|
||||||
|
HashTable,случайный,вставка,0.02124099999491591,2
|
||||||
|
HashTable,случайный,поиск,0.00018730000010691583,2
|
||||||
|
HashTable,случайный,удаление,9.57000011112541e-05,2
|
||||||
|
HashTable,случайный,вставка,0.022729699994670227,3
|
||||||
|
HashTable,случайный,поиск,0.00018990000535268337,3
|
||||||
|
HashTable,случайный,удаление,9.289999434258789e-05,3
|
||||||
|
HashTable,случайный,вставка,0.02114750001055654,4
|
||||||
|
HashTable,случайный,поиск,0.00018650000856723636,4
|
||||||
|
HashTable,случайный,удаление,8.990000060293823e-05,4
|
||||||
|
HashTable,случайный,вставка,0.022626199992373586,5
|
||||||
|
HashTable,случайный,поиск,0.0002082999999402091,5
|
||||||
|
HashTable,случайный,удаление,0.00010770000517368317,5
|
||||||
|
HashTable,отсортированный,вставка,0.020416200000909157,1
|
||||||
|
HashTable,отсортированный,поиск,0.0001990000018849969,1
|
||||||
|
HashTable,отсортированный,удаление,9.100000897888094e-05,1
|
||||||
|
HashTable,отсортированный,вставка,0.0198104000010062,2
|
||||||
|
HashTable,отсортированный,поиск,0.00022190000163391232,2
|
||||||
|
HashTable,отсортированный,удаление,0.00010359998850617558,2
|
||||||
|
HashTable,отсортированный,вставка,0.020307500002672896,3
|
||||||
|
HashTable,отсортированный,поиск,0.00020939999376423657,3
|
||||||
|
HashTable,отсортированный,удаление,9.639999188948423e-05,3
|
||||||
|
HashTable,отсортированный,вставка,0.020547599997371435,4
|
||||||
|
HashTable,отсортированный,поиск,0.00019010000687558204,4
|
||||||
|
HashTable,отсортированный,удаление,8.830000297166407e-05,4
|
||||||
|
HashTable,отсортированный,вставка,0.021012699988204986,5
|
||||||
|
HashTable,отсортированный,поиск,0.00023970000620465726,5
|
||||||
|
HashTable,отсортированный,удаление,0.00011470000026747584,5
|
||||||
|
BST,случайный,вставка,0.0366175000090152,1
|
||||||
|
BST,случайный,поиск,0.00028440001187846065,1
|
||||||
|
BST,случайный,удаление,0.0001773999974830076,1
|
||||||
|
BST,случайный,вставка,0.03504180000163615,2
|
||||||
|
BST,случайный,поиск,0.00026760000037029386,2
|
||||||
|
BST,случайный,удаление,0.00017100000695791095,2
|
||||||
|
BST,случайный,вставка,0.10903169999073725,3
|
||||||
|
BST,случайный,поиск,0.00026849999267142266,3
|
||||||
|
BST,случайный,удаление,0.00016820000018924475,3
|
||||||
|
BST,случайный,вставка,0.03673420000995975,4
|
||||||
|
BST,случайный,поиск,0.00029830000130459666,4
|
||||||
|
BST,случайный,удаление,0.00018350000027567148,4
|
||||||
|
BST,случайный,вставка,0.03608160000294447,5
|
||||||
|
BST,случайный,поиск,0.00028360000578686595,5
|
||||||
|
BST,случайный,удаление,0.00017559999832883477,5
|
||||||
|
BST,отсортированный,вставка,19.357352699997136,1
|
||||||
|
BST,отсортированный,поиск,0.17716789999394678,1
|
||||||
|
BST,отсортированный,удаление,0.0909034999931464,1
|
||||||
|
BST,отсортированный,вставка,17.69543930000509,2
|
||||||
|
BST,отсортированный,поиск,0.14151260000653565,2
|
||||||
|
BST,отсортированный,удаление,0.0668835999967996,2
|
||||||
|
BST,отсортированный,вставка,18.86925250000786,3
|
||||||
|
BST,отсортированный,поиск,0.16006389999529347,3
|
||||||
|
BST,отсортированный,удаление,0.06768140000349376,3
|
||||||
|
BST,отсортированный,вставка,17.811097199999494,4
|
||||||
|
BST,отсортированный,поиск,0.16981530000339262,4
|
||||||
|
BST,отсортированный,удаление,0.0726349000033224,4
|
||||||
|
BST,отсортированный,вставка,16.240639600000577,5
|
||||||
|
BST,отсортированный,поиск,0.1427488000044832,5
|
||||||
|
BST,отсортированный,удаление,0.062093499989714473,5
|
||||||
|
|
|
||||||
|
|
|
@ -2,18 +2,20 @@
|
||||||
|
|
||||||
## 1. Введение
|
## 1. Введение
|
||||||
|
|
||||||
В данной работе были реализованы три структуры данных для хранения телефонного справочника: связный список, хеш-таблица и двоичное дерево поиска. Проведено экспериментальное сравнение производительности операций вставки, поиска и удаления на наборе из **10 000 записей**. Для каждой структуры тестирование выполнялось на двух вариантах входных данных: случайный порядок и отсортированный по имени.
|
В данной работе были реализованы три структуры данных для хранения телефонного справочника: связный список, хеш-таблица и двоичное дерево поиска. Проведено экспериментальное сравнение производительности операций вставки, поиска и удаления на наборе из **10 000 записей**.
|
||||||
|
|
||||||
|
Для каждой структуры тестирование выполнялось на двух вариантах входных данных: случайный порядок и отсортированный по имени. Каждый эксперимент повторялся **5 раз**, в таблице приведены средние значения.
|
||||||
|
|
||||||
## 2. Результаты измерений
|
## 2. Результаты измерений
|
||||||
|
|
||||||
| Структура | Режим | Вставка, с | Поиск, с | Удаление, с |
|
| Структура | Режим | Вставка, с | Поиск, с | Удаление, с |
|
||||||
|-----------|-------|------------|----------|-------------|
|
|-----------|-------|------------|----------|-------------|
|
||||||
| Связный список | случайный | 7.50 | 0.0376 | 0.1337 |
|
| Связный список | случайный | 4.84 | 0.0544 | 0.0308 |
|
||||||
| Связный список | отсортированный | 7.12 | 0.0323 | 0.0263 |
|
| Связный список | отсортированный | 4.60 | 0.0446 | 0.0199 |
|
||||||
| Хеш-таблица | случайный | 0.022 | 0.0001 | 0.0001 |
|
| Хеш-таблица | случайный | 0.0218 | 0.000196 | 0.000096 |
|
||||||
| Хеш-таблица | отсортированный | 0.024 | 0.0001 | 0.0001 |
|
| Хеш-таблица | отсортированный | 0.0204 | 0.000212 | 0.000098 |
|
||||||
| Двоичное дерево | случайный | 0.037 | 0.0001 | 0.0196 |
|
| Двоичное дерево | случайный | 0.0507 | 0.000280 | 0.000175 |
|
||||||
| Двоичное дерево | отсортированный | RecursionError | RecursionError | RecursionError |
|
| Двоичное дерево | отсортированный | 17.99 | 0.1583 | 0.0720 |
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
|
@ -21,28 +23,29 @@
|
||||||
|
|
||||||
### 3.1. Влияние порядка данных на BST
|
### 3.1. Влияние порядка данных на BST
|
||||||
|
|
||||||
При вставке элементов в отсортированном порядке двоичное дерево поиска вырождается в линейный список. Эксперимент подтверждает это: вставка на отсортированных данных вызвала ошибку RecursionError, в то время как на случайных данных заняла 0.037 секунды.
|
При вставке элементов в отсортированном порядке двоичное дерево поиска вырождается в линейный список. Эксперимент подтверждает это: вставка на отсортированных данных заняла **17.99 секунды**, что в **355 раз** медленнее, чем на случайных данных (0.0507 секунды). Поиск и удаление также замедлились примерно в 500 раз.
|
||||||
|
|
||||||
### 3.2. Устойчивость хеш-таблицы к порядку
|
### 3.2. Устойчивость хеш-таблицы к порядку
|
||||||
|
|
||||||
Хеш-таблица использует хеш-функцию, которая равномерно распределяет ключи по корзинам независимо от порядка поступления. В случайном и отсортированном режимах время вставки практически одинаково: 0.022 и 0.024 секунды.
|
Хеш-таблица использует хеш-функцию, которая равномерно распределяет ключи по корзинам независимо от порядка поступления. В случайном и отсортированном режимах время вставки практически одинаково: 0.0218 и 0.0204 секунды. Разница находится в пределах погрешности измерений.
|
||||||
|
|
||||||
### 3.3. Медлительность связного списка при поиске
|
### 3.3. Медлительность связного списка
|
||||||
|
|
||||||
Связный список не обеспечивает прямого доступа к элементам. Время поиска в списке (0.0376 сек) в 376 раз больше, чем в хеш-таблице (0.0001 сек).
|
Связный список не обеспечивает прямого доступа к элементам. Вставка 10000 записей заняла **4.84 секунды** в случайном режиме. Время поиска в списке (0.0544 сек) в **278 раз** больше, чем в хеш-таблице (0.000196 сек). Удаление также значительно медленнее.
|
||||||
|
|
||||||
### 3.4. Сравнение удаления
|
### 3.4. Сравнение удаления
|
||||||
|
|
||||||
- Связный список: 0.1337 сек (требует линейного поиска)
|
- **Связный список**: 0.0308 сек (случайный) — требуется линейный поиск
|
||||||
- Хеш-таблица: 0.0001 сек (мгновенно)
|
- **Хеш-таблица**: 0.000096 сек — практически мгновенно
|
||||||
- BST на случайных данных: 0.0196 сек
|
- **BST на случайных данных**: 0.000175 сек — очень быстро
|
||||||
|
- **BST на отсортированных данных**: 0.0720 сек — в 400 раз медленнее, чем на случайных
|
||||||
|
|
||||||
## 4. Вывод
|
## 4. Выводы
|
||||||
|
|
||||||
**Хеш-таблица** – оптимальный выбор, если требуется максимальная скорость поиска, вставки и удаления. В эксперименте показала стабильно высокую производительность во всех режимах.
|
**Хеш-таблица** – оптимальный выбор, если требуется максимальная скорость поиска, вставки и удаления. В эксперименте показала стабильно высокую производительность во всех режимах (около 0.02 секунды на вставку 10000 записей).
|
||||||
|
|
||||||
**Двоичное дерево поиска** – следует применять, когда необходимо получать данные в отсортированном порядке.
|
**Двоичное дерево поиска** – эффективно на случайных данных, но критически деградирует на отсортированных. При необходимости работы с отсортированными данными следует использовать сбалансированные деревья (AVL, красно-чёрные).
|
||||||
|
|
||||||
**Связный список** – практически непригоден для больших объёмов данных из-за линейной сложности.
|
**Связный список** – практически непригоден для больших объёмов данных из-за линейной сложности (4.84 секунды на вставку 10000 записей).
|
||||||
|
|
||||||
Для телефонного справочника рекомендуется использовать хеш-таблицу.
|
**Для телефонного справочника рекомендуется использовать хеш-таблицу** как наиболее быстрое и предсказуемое решение.
|
||||||
|
|
@ -1,26 +1,42 @@
|
||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
import csv
|
import csv
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
from collections import defaultdict
|
||||||
|
|
||||||
|
# Читаем результаты из CSV и усредняем по 5 повторам
|
||||||
|
data = defaultdict(lambda: defaultdict(lambda: defaultdict(list)))
|
||||||
|
|
||||||
# Читаем результаты из CSV
|
|
||||||
data = {}
|
|
||||||
with open('docs/data/results.csv', 'r', encoding='utf-8') as f:
|
with open('docs/data/results.csv', 'r', encoding='utf-8') as f:
|
||||||
reader = csv.reader(f)
|
reader = csv.reader(f)
|
||||||
next(reader)
|
header = next(reader) # пропускаем заголовок
|
||||||
|
|
||||||
|
# Проверяем, есть ли колонка "Повтор"
|
||||||
|
has_repeat = 'Повтор' in header
|
||||||
|
|
||||||
for row in reader:
|
for row in reader:
|
||||||
struct, mode, op, time = row[0], row[1], row[2], float(row[3])
|
struct = row[0]
|
||||||
if op not in data:
|
mode = row[1]
|
||||||
data[op] = {}
|
op = row[2]
|
||||||
if struct not in data[op]:
|
time_val = float(row[3])
|
||||||
data[op][struct] = {}
|
|
||||||
data[op][struct][mode] = time
|
# Сохраняем все замеры
|
||||||
|
data[op][struct][mode].append(time_val)
|
||||||
|
|
||||||
|
# Усредняем
|
||||||
|
avg_data = {}
|
||||||
|
for op in data:
|
||||||
|
avg_data[op] = {}
|
||||||
|
for struct in data[op]:
|
||||||
|
avg_data[op][struct] = {}
|
||||||
|
for mode in data[op][struct]:
|
||||||
|
times = data[op][struct][mode]
|
||||||
|
avg_data[op][struct][mode] = sum(times) / len(times)
|
||||||
|
|
||||||
# Создаём графики
|
# Создаём графики
|
||||||
operations = ['вставка', 'поиск', 'удаление']
|
operations = ['вставка', 'поиск', 'удаление']
|
||||||
fig, axes = plt.subplots(1, 3, figsize=(15, 5))
|
fig, axes = plt.subplots(1, 3, figsize=(15, 5))
|
||||||
|
|
||||||
# Цвета: синий и красный
|
colors = {'случайный': '#1f77b4', 'отсортированный': '#d62728'}
|
||||||
colors = {'случайный': '#1f77b4', 'отсортированный': '#d62728'} # синий и красный
|
|
||||||
|
|
||||||
for idx, op in enumerate(operations):
|
for idx, op in enumerate(operations):
|
||||||
ax = axes[idx]
|
ax = axes[idx]
|
||||||
|
|
@ -31,10 +47,9 @@ for idx, op in enumerate(operations):
|
||||||
x = np.arange(len(structures))
|
x = np.arange(len(structures))
|
||||||
width = 0.35
|
width = 0.35
|
||||||
|
|
||||||
random_times = [data[op][key].get('случайный', 0) for key in data_keys]
|
random_times = [avg_data[op][key].get('случайный', 0) for key in data_keys]
|
||||||
sorted_times = [data[op][key].get('отсортированный', 0) for key in data_keys]
|
sorted_times = [avg_data[op][key].get('отсортированный', 0) for key in data_keys]
|
||||||
|
|
||||||
# Рисуем столбцы
|
|
||||||
bars1 = ax.bar(x - width/2, random_times, width,
|
bars1 = ax.bar(x - width/2, random_times, width,
|
||||||
label='Случайный', color=colors['случайный'], edgecolor='white', linewidth=1)
|
label='Случайный', color=colors['случайный'], edgecolor='white', linewidth=1)
|
||||||
bars2 = ax.bar(x + width/2, sorted_times, width,
|
bars2 = ax.bar(x + width/2, sorted_times, width,
|
||||||
|
|
@ -45,15 +60,12 @@ for idx, op in enumerate(operations):
|
||||||
ax.set_xticks(x)
|
ax.set_xticks(x)
|
||||||
ax.set_xticklabels(structures, fontsize=10)
|
ax.set_xticklabels(structures, fontsize=10)
|
||||||
|
|
||||||
# Добавляем сетку
|
|
||||||
ax.grid(True, axis='y', alpha=0.3, linestyle='--')
|
ax.grid(True, axis='y', alpha=0.3, linestyle='--')
|
||||||
ax.set_axisbelow(True)
|
ax.set_axisbelow(True)
|
||||||
|
|
||||||
# Убираем верхнюю и правую рамку
|
|
||||||
ax.spines['top'].set_visible(False)
|
ax.spines['top'].set_visible(False)
|
||||||
ax.spines['right'].set_visible(False)
|
ax.spines['right'].set_visible(False)
|
||||||
|
|
||||||
# Добавляем значения на столбцы
|
|
||||||
for bar in bars1:
|
for bar in bars1:
|
||||||
height = bar.get_height()
|
height = bar.get_height()
|
||||||
if height > 0:
|
if height > 0:
|
||||||
|
|
@ -70,16 +82,15 @@ for idx, op in enumerate(operations):
|
||||||
xytext=(0, 3), textcoords="offset points",
|
xytext=(0, 3), textcoords="offset points",
|
||||||
ha='center', va='bottom', fontsize=8)
|
ha='center', va='bottom', fontsize=8)
|
||||||
|
|
||||||
# Легенда ПОД графиками, чтобы не накладывалась
|
|
||||||
fig.legend(labels=['Случайный', 'Отсортированный'],
|
fig.legend(labels=['Случайный', 'Отсортированный'],
|
||||||
loc='lower center', bbox_to_anchor=(0.5, -0.05),
|
loc='lower center', bbox_to_anchor=(0.5, -0.05),
|
||||||
ncol=2, fontsize=11, frameon=True, fancybox=True, shadow=True)
|
ncol=2, fontsize=11, frameon=True, fancybox=True, shadow=True)
|
||||||
|
|
||||||
plt.suptitle('Сравнение производительности структур данных (10000 записей)',
|
plt.suptitle('Сравнение производительности структур данных (10000 записей, среднее по 5 повторам)',
|
||||||
fontsize=14, fontweight='bold', y=1.02)
|
fontsize=14, fontweight='bold', y=1.02)
|
||||||
plt.tight_layout()
|
plt.tight_layout()
|
||||||
plt.subplots_adjust(bottom=0.12) # Оставляем место для легенды снизу
|
plt.subplots_adjust(bottom=0.12)
|
||||||
plt.savefig('docs/data/graph.png', dpi=150, bbox_inches='tight', facecolor='white')
|
plt.savefig('docs/data/graph.png', dpi=150, bbox_inches='tight', facecolor='white')
|
||||||
plt.show()
|
plt.show()
|
||||||
|
|
||||||
print("График сохранён в docs/data/graph.png")
|
print("График сохранён в docs/data/graph.png (использованы средние значения по 5 повторам)")
|
||||||
Loading…
Reference in New Issue
Block a user