From 6491d3a79edacf44f1695efb751bc2cf3f6f3f3b Mon Sep 17 00:00:00 2001 From: zelentsovav Date: Sun, 24 May 2026 20:07:26 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9F=D0=BE=D0=B4=D0=B3=D0=BE=D1=82=D0=BE?= =?UTF-8?q?=D0=B2=D0=BA=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ZelentsovAV/bst.py | 79 ------- ZelentsovAV/config.py | 3 - ZelentsovAV/docs/data/results.csv | 19 -- ZelentsovAV/docs/performance_chart.png | Bin 74870 -> 0 bytes ZelentsovAV/docs/report.md | 85 -------- ZelentsovAV/experiment.py | 90 -------- ZelentsovAV/generator.py | 18 -- ZelentsovAV/hashtable.py | 29 --- ZelentsovAV/linkedlist.py | 47 ---- ZelentsovAV/main.py | 51 ----- ZelentsovAV/rezults.py | 288 ------------------------- 11 files changed, 709 deletions(-) delete mode 100644 ZelentsovAV/bst.py delete mode 100644 ZelentsovAV/config.py delete mode 100644 ZelentsovAV/docs/data/results.csv delete mode 100644 ZelentsovAV/docs/performance_chart.png delete mode 100644 ZelentsovAV/docs/report.md delete mode 100644 ZelentsovAV/experiment.py delete mode 100644 ZelentsovAV/generator.py delete mode 100644 ZelentsovAV/hashtable.py delete mode 100644 ZelentsovAV/linkedlist.py delete mode 100644 ZelentsovAV/main.py delete mode 100644 ZelentsovAV/rezults.py diff --git a/ZelentsovAV/bst.py b/ZelentsovAV/bst.py deleted file mode 100644 index 47d1144..0000000 --- a/ZelentsovAV/bst.py +++ /dev/null @@ -1,79 +0,0 @@ -def bst_insert(root, name, phone): - new_node = {'name': name, 'phone': phone, 'left': None, 'right': None} - - if root is None: - return new_node - - current = root - while True: - if name < current['name']: - if current['left'] is None: - current['left'] = new_node - break - else: - current = current['left'] - elif name > current['name']: - if current['right'] is None: - current['right'] = new_node - break - else: - current = current['right'] - else: - current['phone'] = phone - break - - return root - -def bst_find(root, name): #Итеративный поиск в BST - current = root - while current is not None: - if name == current['name']: - return current['phone'] - elif name < current['name']: - current = current['left'] - else: - current = current['right'] - return None - -def bst_find_min(root): #Поиск минимального узла - current = root - while current['left'] is not None: - current = current['left'] - return current - -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'] - elif root['right'] is None: - return root['left'] - else: - min_node = bst_find_min(root['right']) - 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, records=None): #Возвращает отсортированные записи - if records is None: - records = [] - - stack = [] - current = root - - while stack or current: - while current is not None: - stack.append(current) - current = current['left'] - current = stack.pop() - records.append((current['name'], current['phone'])) - current = current['right'] - - return records \ No newline at end of file diff --git a/ZelentsovAV/config.py b/ZelentsovAV/config.py deleted file mode 100644 index d1eb5b4..0000000 --- a/ZelentsovAV/config.py +++ /dev/null @@ -1,3 +0,0 @@ -N = 10000 # Количество записей -REPEATS = 5 # Количество повторений каждого эксперимента -HASH_TABLE_SIZE = 1000 # Размер хеш-таблиц \ No newline at end of file diff --git a/ZelentsovAV/docs/data/results.csv b/ZelentsovAV/docs/data/results.csv deleted file mode 100644 index 466ba23..0000000 --- a/ZelentsovAV/docs/data/results.csv +++ /dev/null @@ -1,19 +0,0 @@ -Структура,Режим,Операция,Повтор1,Повтор2,Повтор3,Повтор4,Повтор5,Среднее,Стд_откл -linkedlist,случайный,вставка,6.12412660010159,6.453428599983454,6.0159983998164535,5.846197799779475,6.687424399890006,6.225435159914196,0.3044218200660184 -linkedlist,случайный,поиск,0.04134450014680624,0.04073229990899563,0.042916799895465374,0.04113580007106066,0.05696159973740578,0.044618199951946734,0.006216087497843716 -linkedlist,случайный,удаление,0.026781500317156315,0.027109399437904358,0.030823000706732273,0.02719919942319393,0.03118100017309189,0.028618820011615753,0.001954103193777089 -linkedlist,отсортированный,вставка,6.631766900420189,5.748658500611782,5.798537000082433,6.062226499430835,5.308409399352968,5.909919659979641,0.43462320783889524 -linkedlist,отсортированный,поиск,0.006313499994575977,0.005670599639415741,0.005590200424194336,0.005645200610160828,0.005786299705505371,0.005801160074770451,0.0002640402924000638 -linkedlist,отсортированный,удаление,0.0005609998479485512,0.0005288999527692795,0.0005288999527692795,0.0006311992183327675,0.0005285991355776787,0.0005557196214795113,3.9747101397961354e-05 -hashtable,случайный,вставка,0.4039090992882848,0.43919940013438463,0.5127053996548057,0.4458825998008251,0.5722195003181696,0.47478319983929396,0.06009411868526661 -hashtable,случайный,поиск,0.0011500995606184006,0.0015127994120121002,0.0014458000659942627,0.0015266994014382362,0.0016105994582176208,0.001449199579656124,0.0001584761558930157 -hashtable,случайный,удаление,0.0006000008434057236,0.0006478000432252884,0.0006513996049761772,0.0006491998210549355,0.0006536999717354774,0.0006404200568795205,2.0308460750476644e-05 -hashtable,отсортированный,вставка,0.41475220024585724,0.36477189976722,0.4018732002004981,0.34626630041748285,0.3364391000941396,0.37282054014503957,0.030645843485620654 -hashtable,отсортированный,поиск,0.00014910008758306503,0.00021160021424293518,0.00014139991253614426,0.00013990048319101334,0.00014150049537420273,0.0001567002385854721,2.763741512756699e-05 -hashtable,отсортированный,удаление,0.00010520033538341522,0.00011090002954006195,9.95006412267685e-05,9.809993207454681e-05,9.940005838871002e-05,0.0001026201993227005,4.811371049160917e-06 -bst,случайный,вставка,0.02877839934080839,0.023240000009536743,0.023904399946331978,0.02267790026962757,0.02133959997445345,0.023988059908151626,0.0025394803712577006 -bst,случайный,поиск,0.00018490012735128403,0.00017419923096895218,0.0001809997484087944,0.0001767994835972786,0.0001687007024884224,0.00017711985856294632,5.569578481417004e-06 -bst,случайный,удаление,0.00012159999459981918,0.0001150006428360939,0.0001226002350449562,0.00011949986219406128,0.00011199992150068283,0.00011814013123512268,4.0316401567625745e-06 -bst,отсортированный,вставка,6.140015699900687,7.042814400047064,6.089983900077641,7.145617099478841,7.014688899740577,6.686623999848962,0.46902726732451255 -bst,отсортированный,поиск,0.0004746001213788986,0.0004603993147611618,0.0005575995892286301,0.0004612002521753311,0.0005747005343437195,0.0005056999623775482,4.9908362408772585e-05 -bst,отсортированный,удаление,0.0007436992600560188,0.0007255999371409416,0.0007277000695466995,0.0007218997925519943,0.0010781008750200272,0.0007993999868631362,0.00013954953359056988 diff --git a/ZelentsovAV/docs/performance_chart.png b/ZelentsovAV/docs/performance_chart.png deleted file mode 100644 index fd663f17d1c439fa3ea8a96e65152542081a1c8e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 74870 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 diff --git a/ZelentsovAV/docs/report.md b/ZelentsovAV/docs/report.md deleted file mode 100644 index 2febb20..0000000 --- a/ZelentsovAV/docs/report.md +++ /dev/null @@ -1,85 +0,0 @@ -# Отчёт по лабораторной работе - -## Цель работы - -Реализовать три структуры данных «с нуля» (связный список, хеш-таблица, двоичное дерево поиска), применить их для хранения записей телефонного справочника и экспериментально сравнить производительность основных операций. - -## Параметры эксперимента - -- Количество записей: 10000 -- Количество повторов каждого теста: 5 -- Размер хеш-таблицы: 1000 корзин - -## Результаты экспериментов - -### 1. Связный список - -| Режим | Вставка (сек) | Поиск (сек) | Удаление (сек) | -|-------|---------------|-------------|----------------| -| Случайный | 6.2254 | 0.0446 | 0.0286 | -| Отсортированный | 5.9099 | 0.0058 | 0.0006 | - -### 2. Хеш-таблица - -| Режим | Вставка (сек) | Поиск (сек) | Удаление (сек) | -|-------|---------------|-------------|----------------| -| Случайный | 0.4748 | 0.0014 | 0.0006 | -| Отсортированный | 0.3728 | 0.0002 | 0.0001 | - -### 3. Двоичное дерево поиска (BST) - -| Режим | Вставка (сек) | Поиск (сек) | Удаление (сек) | -|-------|---------------|-------------|----------------| -| Случайный | 0.0240 | 0.0002 | 0.0001 | -| Отсортированный | 6.6866 | 0.0005 | 0.0008 | - -## Анализ результатов - -### 1. Влияние порядка данных на BST -При добавлении уже отсортированных элементов BST вырождается в линейную структуру — сложность падает с O(log n) до O(n). -Время вставки выросло с 0.0240 до 6.6866 секунд — замедление в 278.7 раза. - -### 2. Почему хеш-таблица не чувствительна к порядку - -Хеш-функция равномерно распределяет ключи по корзинам независимо от их исходного порядка. Поэтому последовательность добавления практически не влияет на производительность. -Сравнение случайного и упорядоченного ввода: -- Случайный режим: 0.4748 с -- Упорядоченный режим: 0.3728 с -- Различие: 0.79 - -### 3. Почему связный список медленный при поиске - -Поиск в связном списке требует линейного обхода O(n) — структура не поддерживает произвольный доступ. Это делает его непригодным для крупных справочников, где нужен быстрый поиск по ключу. - -Сравнение скорости поиска на случайных данных: -- LinkedList: 0.0446 сек -- HashTable: 0.0014 сек (преимущество в 30.8) -- BST: 0.0002 сек - -### 4. Сравнение удаления - -| Структура | Сложность | Время на 50 удалений (случайные данные) | -|-----------|-----------|------------------------------------------| -| Связный список | O(n) | 0.0286 сек| -| Хеш-таблица | O(1) в среднем | 0.0006 сек | -| BST | O(log n) в среднем | 0.0001 сек | - -## Вывод: - -| Задача | Рекомендация | Почему | -|--------|-------------|--------| -| Частый поиск | Хеш-таблица | O(1) в среднем, не зависит от порядка | -| Частые вставки/удаления | Хеш-таблица | Амортизированное O(1) | -| Нужен отсортированный вывод | Сбалансированное дерево (AVL/Red-Black) | In-order обход даёт сортировку | -| Мало данных (<100 элементов) | Связный список или массив | Простота, накладные расходы не оправданы | -| Последовательный доступ (очередь/стек) | Связный список | Вставка/удаление в начало/конец за O(1) | - -## Заключение -Проведённый эксперимент подтверждает теоретические оценки сложности: - -1. **Небалансированное BST это плохой выбор** при работе с реальными данными, которые могут оказаться упорядоченными. Деградация до O(n) делает его непригодным для надёжных систем. - -2. **Хеш-таблица показывает стабильные результаты** вне зависимости от порядка входных данных — ключевое преимущество для телефонного справочника с произвольными именами абонентов. - -3. **Связный список — нишевый инструмент**, эффективный только при работе с малыми объёмами данных. - diff --git a/ZelentsovAV/experiment.py b/ZelentsovAV/experiment.py deleted file mode 100644 index 505d5b2..0000000 --- a/ZelentsovAV/experiment.py +++ /dev/null @@ -1,90 +0,0 @@ -import time -import numpy as np -from linkedlist import ll_insert, ll_find, ll_delete -from hashtable import ht_create, ht_insert, ht_find, ht_delete -from bst import bst_insert, bst_find, bst_delete - -def measure_insert(records, struct_type, params=None): #Замер времени вставки всех записей - start = time.perf_counter() - - if struct_type == 'linkedlist': - head = None - for name, phone in records: - head = ll_insert(head, name, phone) - result = head - - elif struct_type == 'hashtable': - size = params.get('size', 1000) if params else 1000 - buckets = ht_create(size) - for name, phone in records: - ht_insert(buckets, name, phone) - result = buckets - - elif struct_type == 'bst': - root = None - for name, phone in records: - root = bst_insert(root, name, phone) - result = root - - end = time.perf_counter() - return end - start, result - -def measure_find(structure, names_to_find, struct_type): #Замер времени поиска записей - start = time.perf_counter() - - for name in names_to_find: - if struct_type == 'linkedlist': - ll_find(structure, name) - elif struct_type == 'hashtable': - ht_find(structure, name) - elif struct_type == 'bst': - bst_find(structure, name) - - end = time.perf_counter() - return end - start - -def measure_delete(structure, names_to_delete, struct_type): #Замер времени удаления записей - start = time.perf_counter() - - for name in names_to_delete: - if struct_type == 'linkedlist': - structure = ll_delete(structure, name) - elif struct_type == 'hashtable': - ht_delete(structure, name) - elif struct_type == 'bst': - structure = bst_delete(structure, name) - - end = time.perf_counter() - return end - start, structure - -def run_single_experiment(struct_type, mode, data_records, names_to_find, names_to_delete, repeats, params=None): #Запуск одного эксперимента - insert_times = [] - find_times = [] - delete_times = [] - - for i in range(repeats): - if struct_type == 'hashtable': - insert_time, structure = measure_insert(data_records, struct_type, params) - else: - insert_time, structure = measure_insert(data_records, struct_type) - insert_times.append(insert_time) - - find_time = measure_find(structure, names_to_find, struct_type) - find_times.append(find_time) - - delete_time, structure = measure_delete(structure, names_to_delete, struct_type) - delete_times.append(delete_time) - - return { - 'structure': struct_type, - 'mode': mode, - 'insert_mean': np.mean(insert_times), - 'insert_std': np.std(insert_times), - 'insert_all': insert_times, - 'find_mean': np.mean(find_times), - 'find_std': np.std(find_times), - 'find_all': find_times, - 'delete_mean': np.mean(delete_times), - 'delete_std': np.std(delete_times), - 'delete_all': delete_times - } \ No newline at end of file diff --git a/ZelentsovAV/generator.py b/ZelentsovAV/generator.py deleted file mode 100644 index 3691bec..0000000 --- a/ZelentsovAV/generator.py +++ /dev/null @@ -1,18 +0,0 @@ -import random - -def generate_test_data(N): #Генерирует N записей с именами User_00000 ... User_N-1 - records = [(f"User_{i:05d}", f"+7-999-{i:05d}") for i in range(N)] - - records_shuffled = records.copy() - random.shuffle(records_shuffled) - - records_sorted = sorted(records, key=lambda x: x[0]) - - return records, records_shuffled, records_sorted - -def get_names_for_operations(records, num_find=100, num_delete=50, num_nonexistent=10): #Подготавливает имена для операций поиска и удаления - existing_names = [name for name, _ in records[:num_find + num_delete]] - names_to_find = existing_names[:num_find] + [f"None_{i}" for i in range(num_nonexistent)] - names_to_delete = existing_names[num_find:num_find + num_delete] - - return names_to_find, names_to_delete \ No newline at end of file diff --git a/ZelentsovAV/hashtable.py b/ZelentsovAV/hashtable.py deleted file mode 100644 index 363f9f1..0000000 --- a/ZelentsovAV/hashtable.py +++ /dev/null @@ -1,29 +0,0 @@ -from linkedlist import ll_insert, ll_find, ll_delete, ll_list_all - -def hash_function(name, size): - return sum(ord(c) for c in name) % size - -def ht_create(size): - return [None] * size - -def ht_insert(buckets, name, phone): - index = hash_function(name, len(buckets)) - buckets[index] = ll_insert(buckets[index], name, phone) - -def ht_find(buckets, name): - index = hash_function(name, len(buckets)) - return ll_find(buckets[index], name) - -def ht_delete(buckets, name): - index = hash_function(name, len(buckets)) - buckets[index] = ll_delete(buckets[index], name) - -def ht_list_all(buckets): - records = [] - for bucket in buckets: - current = bucket - while current is not None: - records.append((current['name'], current['phone'])) - current = current['next'] - records.sort(key=lambda x: x[0]) - return records \ No newline at end of file diff --git a/ZelentsovAV/linkedlist.py b/ZelentsovAV/linkedlist.py deleted file mode 100644 index d83ca7d..0000000 --- a/ZelentsovAV/linkedlist.py +++ /dev/null @@ -1,47 +0,0 @@ -def ll_insert(head, name, phone): #Oбновление записи в связном списке - if head is None: - return {'name': name, 'phone': phone, 'next': None} - current = head - while current is not None: - if current['name'] == name: - current['phone'] = phone - return head - current = current['next'] - new_node = {'name': name, 'phone': phone, 'next': None} - current = head - while current['next'] is not None: - current = current['next'] - current['next'] = new_node - return head - -def ll_find(head, name): #Поиск телефона по имени - current = head - while current is not None: - if current['name'] == name: - return current['phone'] - current = current['next'] - return None - -def ll_delete(head, name): #Удаление записи по имени - if head is None: - return None - - if head['name'] == name: - return head['next'] - - current = head - while current['next'] is not None: - if current['next']['name'] == name: - current['next'] = current['next']['next'] - return head - current = current['next'] - return head - -def ll_list_all(head): #Сбор всех записей и сортировка по имени - records = [] - current = head - while current is not None: - records.append((current['name'], current['phone'])) - current = current['next'] - records.sort(key=lambda x: x[0]) - return records \ No newline at end of file diff --git a/ZelentsovAV/main.py b/ZelentsovAV/main.py deleted file mode 100644 index 6d34384..0000000 --- a/ZelentsovAV/main.py +++ /dev/null @@ -1,51 +0,0 @@ -from config import N, REPEATS, HASH_TABLE_SIZE -from generator import generate_test_data, get_names_for_operations -from experiment import run_single_experiment -from rezults import save_to_csv, plot_results, print_analysis, save_report_md - -def main(): - print(f"Количество записей: {N}") - print(f"Количество повторов: {REPEATS}") - print(f"Размер хеш-таблицы: {HASH_TABLE_SIZE}") - print() - - records, records_shuffled, records_sorted = generate_test_data(N) - names_to_find, names_to_delete = get_names_for_operations(records) - - experiments = [ - ('linkedlist', 'случайный', records_shuffled), - ('linkedlist', 'отсортированный', records_sorted), - ('hashtable', 'случайный', records_shuffled), - ('hashtable', 'отсортированный', records_sorted), - ('bst', 'случайный', records_shuffled), - ('bst', 'отсортированный', records_sorted), - ] - - results = [] - - for struct_type, mode, data_records in experiments: - print(f"Тестирование: {struct_type} - {mode}") - - params = {'size': HASH_TABLE_SIZE} if struct_type == 'hashtable' else None - - result = run_single_experiment( - struct_type, mode, data_records, - names_to_find, names_to_delete, - REPEATS, params - ) - - results.append(result) - - print(f" Insert: {result['insert_mean']:.4f} ± {result['insert_std']:.4f} sec") - print(f" Find: {result['find_mean']:.4f} ± {result['find_std']:.4f} sec") - print(f" Delete: {result['delete_mean']:.4f} ± {result['delete_std']:.4f} sec") - print() - - save_to_csv(results) - plot_results(results) - save_report_md(results) - print_analysis(results) - - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/ZelentsovAV/rezults.py b/ZelentsovAV/rezults.py deleted file mode 100644 index 99ab814..0000000 --- a/ZelentsovAV/rezults.py +++ /dev/null @@ -1,288 +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} с -- Упорядоченный режим: {ht_sorted_insert:.4f} с -- Различие: {ht_sorted_insert/ht_random_insert:.2f} - -### 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. **Связный список — нишевый инструмент**, эффективный только при работе с малыми объёмами данных. - -""" - - 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