diff --git a/SmirnovaVYu/docs/data/results_analyzer.py b/SmirnovaVYu/docs/data/results_analyzer.py deleted file mode 100644 index 60b740b1..00000000 --- a/SmirnovaVYu/docs/data/results_analyzer.py +++ /dev/null @@ -1,297 +0,0 @@ -import csv -import os -import numpy as np -from matplotlib import pyplot as plt - - -def ensure_directories(): - os.makedirs('docs/data', exist_ok=True) - - -def save_to_csv(results, filename="docs/data/results.csv"): - ensure_directories() - - with open(filename, 'w', newline='', encoding='utf-8') as f: - writer = csv.writer(f) - writer.writerow(['Структура', 'Режим', 'Операция', - 'Повтор1', 'Повтор2', 'Повтор3', 'Повтор4', 'Повтор5', - 'Среднее', 'Стд_откл']) - - for res in results: - struct_name = res['structure'] - mode = res['mode'] - - for op, times, mean, std in [ - ('вставка', res['insert_all'], res['insert_mean'], res['insert_std']), - ('поиск', res['find_all'], res['find_mean'], res['find_std']), - ('удаление', res['delete_all'], res['delete_mean'], res['delete_std']) - ]: - row = [struct_name, mode, op] + times + [mean, std] - writer.writerow(row) - - -def plot_results(results, filename="docs/performance_chart.png"): - ensure_directories() - struct_names = { - 'linkedlist': 'LinkedList', - 'hashtable': 'HashTable', - 'bst': 'BST' - } - - operations = ['insert', 'find', 'delete'] - op_names = {'insert': 'Вставка', 'find': 'Поиск', 'delete': 'Удаление'} - random_data = {} - sorted_data = {} - - for res in results: - struct_name = struct_names.get(res['structure'], res['structure']) - mode = res['mode'] - - if mode == 'случайный': - random_data[struct_name] = { - 'insert': res['insert_mean'], - 'find': res['find_mean'], - 'delete': res['delete_mean'] - } - else: - sorted_data[struct_name] = { - 'insert': res['insert_mean'], - 'find': res['find_mean'], - 'delete': res['delete_mean'] - } - - structure_order = ['LinkedList', 'HashTable', 'BST'] - - fig, axes = plt.subplots(1, 3, figsize=(15, 5)) - - for idx, op in enumerate(operations): - ax = axes[idx] - - x = np.arange(len(structure_order)) - width = 0.35 - - random_means = [] - sorted_means = [] - - for struct in structure_order: - if struct in random_data: - random_means.append(random_data[struct][op]) - else: - random_means.append(0) - - if struct in sorted_data: - sorted_means.append(sorted_data[struct][op]) - else: - sorted_means.append(0) - - if not random_means and not sorted_means: - print(f" Нет данных для операции {op}") - continue - - bars1 = ax.bar(x - width/2, random_means, width, - label='Случайный порядок', color='skyblue') - bars2 = ax.bar(x + width/2, sorted_means, width, - label='Отсортированный порядок', color='salmon') - - ax.set_xlabel('Структура данных') - ax.set_ylabel('Время (секунды)') - ax.set_title(f'{op_names.get(op, op)}') - ax.set_xticks(x) - ax.set_xticklabels(structure_order) - ax.legend() - - for bar in bars1 + bars2: - height = bar.get_height() - if height > 0: - ax.annotate(f'{height:.3f}', - xy=(bar.get_x() + bar.get_width() / 2, height), - xytext=(0, 3), textcoords="offset points", - ha='center', va='bottom', fontsize=8) - - plt.tight_layout() - plt.savefig(filename, dpi=150) - plt.show() - -def save_report_md(results, filename="docs/report.md"): - ensure_directories() - - results_dict = {} - for res in results: - key = (res['structure'], res['mode']) - results_dict[key] = res - - def get_val(struct, mode, field): - key = (struct, mode) - if key in results_dict: - return results_dict[key][field] - return 0.0 - - ll_random_insert = get_val('linkedlist', 'случайный', 'insert_mean') - ll_random_find = get_val('linkedlist', 'случайный', 'find_mean') - ll_random_delete = get_val('linkedlist', 'случайный', 'delete_mean') - ll_sorted_insert = get_val('linkedlist', 'отсортированный', 'insert_mean') - ll_sorted_find = get_val('linkedlist', 'отсортированный', 'find_mean') - ll_sorted_delete = get_val('linkedlist', 'отсортированный', 'delete_mean') - - ht_random_insert = get_val('hashtable', 'случайный', 'insert_mean') - ht_random_find = get_val('hashtable', 'случайный', 'find_mean') - ht_random_delete = get_val('hashtable', 'случайный', 'delete_mean') - ht_sorted_insert = get_val('hashtable', 'отсортированный', 'insert_mean') - ht_sorted_find = get_val('hashtable', 'отсортированный', 'find_mean') - ht_sorted_delete = get_val('hashtable', 'отсортированный', 'delete_mean') - - bst_random_insert = get_val('bst', 'случайный', 'insert_mean') - bst_random_find = get_val('bst', 'случайный', 'find_mean') - bst_random_delete = get_val('bst', 'случайный', 'delete_mean') - bst_sorted_insert = get_val('bst', 'отсортированный', 'insert_mean') - bst_sorted_find = get_val('bst', 'отсортированный', 'find_mean') - bst_sorted_delete = get_val('bst', 'отсортированный', 'delete_mean') - - from datetime import datetime - - report_content = f"""# Отчёт по лабораторной работе - -## Цель работы - -Реализовать три структуры данных «с нуля» (связный список, хеш-таблица, двоичное дерево поиска), применить их для хранения записей телефонного справочника и экспериментально сравнить производительность основных операций. - -## Параметры эксперимента - -- Количество записей: 10000 -- Количество повторов каждого теста: 5 -- Размер хеш-таблицы: 1000 корзин - -## Результаты экспериментов - -### 1. Связный список - -| Режим | Вставка (сек) | Поиск (сек) | Удаление (сек) | -|-------|---------------|-------------|----------------| -| Случайный | {ll_random_insert:.4f} | {ll_random_find:.4f} | {ll_random_delete:.4f} | -| Отсортированный | {ll_sorted_insert:.4f} | {ll_sorted_find:.4f} | {ll_sorted_delete:.4f} | - -### 2. Хеш-таблица - -| Режим | Вставка (сек) | Поиск (сек) | Удаление (сек) | -|-------|---------------|-------------|----------------| -| Случайный | {ht_random_insert:.4f} | {ht_random_find:.4f} | {ht_random_delete:.4f} | -| Отсортированный | {ht_sorted_insert:.4f} | {ht_sorted_find:.4f} | {ht_sorted_delete:.4f} | - -### 3. Двоичное дерево поиска (BST) - -| Режим | Вставка (сек) | Поиск (сек) | Удаление (сек) | -|-------|---------------|-------------|----------------| -| Случайный | {bst_random_insert:.4f} | {bst_random_find:.4f} | {bst_random_delete:.4f} | -| Отсортированный | {bst_sorted_insert:.4f} | {bst_sorted_find:.4f} | {bst_sorted_delete:.4f} | - -## Анализ результатов - -### 1. Влияние порядка данных на BST - -На отсортированных данных BST деградирует с O(log n) до O(n). -Время вставки увеличилось с {bst_random_insert:.4f} до {bst_sorted_insert:.4f} секунд — в {bst_sorted_insert/bst_random_insert:.1f} раз. - -### 2. Почему хеш-таблица не чувствительна к порядку - -Хеш-функция распределяет элементы случайно, порядок ввода не влияет на позицию элемента. - -Разница между случайным и отсортированным порядком: -- Вставка: {ht_random_insert:.4f} vs {ht_sorted_insert:.4f} -- Отношение: {ht_sorted_insert/ht_random_insert:.2f}x (почти не чувствительна) - -### 3. Почему связный список медленный при поиске - -Поиск требует последовательного прохода O(n) без возможности индексации. -Поэтому связный список хорош только когда записей мало. -Для больших телефонных справочников он не подходит. - -Сравнение скорости поиска (случайные данные): -- LinkedList: {ll_random_find:.4f} сек -- HashTable: {ht_random_find:.4f} сек (в {ll_random_find/ht_random_find:.1f} раз быстрее) -- BST: {bst_random_find:.4f} сек - -### 4. Сравнение удаления - -| Структура | Сложность | Время на 50 удалений (случайные данные) | -|-----------|-----------|------------------------------------------| -| Связный список | O(n) | {ll_random_delete:.4f} сек | -| Хеш-таблица | O(1) в среднем | {ht_random_delete:.4f} сек | -| BST | O(log n) в среднем | {bst_random_delete:.4f} сек | - -## Вывод: - -| Задача | Рекомендация | Почему | -|--------|-------------|--------| -| Частый поиск | Хеш-таблица | O(1) в среднем, не зависит от порядка | -| Частые вставки/удаления | Хеш-таблица | Амортизированное O(1) | -| Нужен отсортированный вывод | Сбалансированное дерево (AVL/Red-Black) | In-order обход даёт сортировку | -| Мало данных (<100 элементов) | Связный список или массив | Простота, накладные расходы не оправданы | -| Последовательный доступ (очередь/стек) | Связный список | Вставка/удаление в начало/конец за O(1) | - -## Заключение - -Эксперимент наглядно демонстрирует: -1. **BST без балансировки опасен** — на отсортированных данных он деградирует до O(n) -2. **Хеш-таблица стабильна** — её производительность не зависит от порядка входных данных -3. **Связный список** подходит только для специфических задач с малым объёмом данных - -## Дата выполнения - -{datetime.now().strftime('%Y-%m-%d %H:%M:%S')} -""" - - with open(filename, 'w', encoding='utf-8') as f: - f.write(report_content) - - -def print_analysis(results): - print("\n" + "="*60) - print("Анализ резов") - print("="*60) - - best_insert = min(results, key=lambda x: x['insert_mean']) - best_find = min(results, key=lambda x: x['find_mean']) - best_delete = min(results, key=lambda x: x['delete_mean']) - - print(f"\n Лучшая для вставки: {best_insert['structure']} ({best_insert['mode']}) - {best_insert['insert_mean']:.4f} сек") - print(f" Лучшая для поиска: {best_find['structure']} ({best_find['mode']}) - {best_find['find_mean']:.4f} сек") - print(f" Лучшая для удаления: {best_delete['structure']} ({best_delete['mode']}) - {best_delete['delete_mean']:.4f} сек") - - bst_random = None - bst_sorted = None - for res in results: - if res['structure'] == 'bst' and res['mode'] == 'случайный': - bst_random = res - elif res['structure'] == 'bst' and res['mode'] == 'отсортированный': - bst_sorted = res - - if bst_random and bst_sorted: - print("\n Влияние порядка данных на BST:") - print(f" Вставка: случайный {bst_random['insert_mean']:.4f} сек vs отсортированный {bst_sorted['insert_mean']:.4f} сек") - print(f" Деградация в {bst_sorted['insert_mean']/bst_random['insert_mean']:.1f}x") - - ht_random = None - ht_sorted = None - for res in results: - if res['structure'] == 'hashtable' and res['mode'] == 'случайный': - ht_random = res - elif res['structure'] == 'hashtable' and res['mode'] == 'отсортированный': - ht_sorted = res - - if ht_random and ht_sorted: - print("\n Чувствительность хеш-таблицы к порядку:") - print(f" Вставка: случайный {ht_random['insert_mean']:.4f} сек vs отсортированный {ht_sorted['insert_mean']:.4f} сек") - print(f" Отношение: {ht_sorted['insert_mean']/ht_random['insert_mean']:.2f}x (почти не чувствительна)") - - ll_random = None - for res in results: - if res['structure'] == 'linkedlist' and res['mode'] == 'случайный': - ll_random = res - elif res['structure'] == 'hashtable' and res['mode'] == 'случайный': - ht_random = res - - if ll_random and ht_random: - print("\n Сравнение скорости поиска:") - print(f" LinkedList: {ll_random['find_mean']:.4f} сек") - print(f" HashTable: {ht_random['find_mean']:.4f} сек") - print(f" HashTable быстрее в {ll_random['find_mean']/ht_random['find_mean']:.1f} раз") \ No newline at end of file