From 2cff4ebb9c523b4f8f1b09e2a690b644ad76c469 Mon Sep 17 00:00:00 2001 From: kalinovskiymi Date: Sun, 24 May 2026 22:09:25 +0000 Subject: [PATCH] =?UTF-8?q?=D0=A3=D0=B4=D0=B0=D0=BB=D0=B8=D1=82=D1=8C=20ka?= =?UTF-8?q?linovskiymi/docs/task=5F1.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kalinovskiymi/docs/task_1.py | 377 ----------------------------------- 1 file changed, 377 deletions(-) delete mode 100644 kalinovskiymi/docs/task_1.py diff --git a/kalinovskiymi/docs/task_1.py b/kalinovskiymi/docs/task_1.py deleted file mode 100644 index ee7c141..0000000 --- a/kalinovskiymi/docs/task_1.py +++ /dev/null @@ -1,377 +0,0 @@ -import sys - -sys.setrecursionlimit(10000) - -import time -import random -import csv -import os -import matplotlib.pyplot as plt -import numpy as np - - -def ll_insert(head, name, phone): - new_node = {'name': name, 'phone': phone, 'next': None} - if head is None: - return new_node - if head['name'] > name: - new_node['next'] = head - return new_node - current = head - while current['next'] is not None and current['next']['name'] < name: - current = current['next'] - if current['name'] == name: - current['phone'] = phone - return head - new_node['next'] = 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): - result = [] - current = head - while current is not None: - result.append((current['name'], current['phone'])) - current = current['next'] - result.sort(key=lambda x: x[0]) - return result - - -def ht_insert(buckets, name, phone): - index = hash(name) % len(buckets) - buckets[index] = ll_insert(buckets[index], name, phone) - - -def ht_find(buckets, name): - index = hash(name) % len(buckets) - return ll_find(buckets[index], name) - - -def ht_delete(buckets, name): - index = hash(name) % len(buckets) - buckets[index] = ll_delete(buckets[index], name) - - -def ht_list_all(buckets): - result = [] - for bucket in buckets: - if bucket is not None: - current = bucket - while current is not None: - result.append((current['name'], current['phone'])) - current = current['next'] - result.sort(key=lambda x: x[0]) - return result - - -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): - 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_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): - result = [] - - def inorder(node): - if node is not None: - inorder(node['left']) - result.append((node['name'], node['phone'])) - inorder(node['right']) - - inorder(root) - return result - - -def generate_records(n, mode='shuffled'): - names = [f"User_{i:05d}" for i in range(n)] - if mode == 'shuffled': - random.shuffle(names) - records = [(name, f"Phone_{i}") for i, name in enumerate(names)] - return records - - -def benchmark_insert(structure_type, records, buckets_size=512): - if structure_type == 'LinkedList': - head = None - start = time.perf_counter() - for name, phone in records: - head = ll_insert(head, name, phone) - end = time.perf_counter() - return end - start, head - elif structure_type == 'HashTable': - buckets = [None] * buckets_size - start = time.perf_counter() - for name, phone in records: - ht_insert(buckets, name, phone) - end = time.perf_counter() - return end - start, buckets - elif structure_type == 'BST': - root = None - start = time.perf_counter() - for name, phone in records: - root = bst_insert(root, name, phone) - end = time.perf_counter() - return end - start, root - - -def benchmark_find(structure_type, structure, names): - start = time.perf_counter() - if structure_type == 'LinkedList': - for name in names: - ll_find(structure, name) - elif structure_type == 'HashTable': - for name in names: - ht_find(structure, name) - elif structure_type == 'BST': - for name in names: - bst_find(structure, name) - end = time.perf_counter() - return end - start - - -def benchmark_delete(structure_type, structure, names): - start = time.perf_counter() - if structure_type == 'LinkedList': - head = structure - for name in names: - head = ll_delete(head, name) - end = time.perf_counter() - return end - start, head - elif structure_type == 'HashTable': - buckets = structure - for name in names: - ht_delete(buckets, name) - end = time.perf_counter() - return end - start, buckets - elif structure_type == 'BST': - root = structure - for name in names: - root = bst_delete(root, name) - end = time.perf_counter() - return end - start, root - - -def benchmark_list_all(structure_type, structure): - start = time.perf_counter() - if structure_type == 'LinkedList': - ll_list_all(structure) - elif structure_type == 'HashTable': - ht_list_all(structure) - elif structure_type == 'BST': - bst_list_all(structure) - end = time.perf_counter() - return end - start - - -def main(): - random.seed(42) - N = 1000 - REPETITIONS = 5 - - all_results = [] - structures = ['LinkedList', 'HashTable', 'BST'] - modes = ['shuffled', 'sorted'] - - os.makedirs('docs/data', exist_ok=True) - - for mode in modes: - records = generate_records(N, mode) - find_names = [random.choice(records)[0] for _ in range(100)] + [f"None_{i}" for i in range(10)] - delete_names = [random.choice(records)[0] for _ in range(50)] - - for struct in structures: - print(f"Тестирую {struct} на {mode} данных...") - for rep in range(REPETITIONS): - insert_time, structure = benchmark_insert(struct, records) - all_results.append([struct, mode, 'insert', insert_time, rep + 1]) - - find_time = benchmark_find(struct, structure, find_names) - all_results.append([struct, mode, 'find', find_time, rep + 1]) - - delete_time, _ = benchmark_delete(struct, structure, delete_names) - all_results.append([struct, mode, 'delete', delete_time, rep + 1]) - - with open('docs/data/results.csv', 'w', newline='') as f: - writer = csv.writer(f) - writer.writerow(['structure', 'order', 'operation', 'time', 'run']) - writer.writerows(all_results) - - print("\nCSV сохранён в docs/data/results.csv") - - data = {} - for row in all_results: - key = (row[0], row[1], row[2]) - if key not in data: - data[key] = [] - data[key].append(row[3]) - - averaged = [] - for key, times in data.items(): - avg_time = sum(times) / len(times) - averaged.append([key[0], key[1], key[2], avg_time]) - - print("\nУСРЕДНЁННЫЕ РЕЗУЛЬТАТЫ (сек):") - print(f"{'Структура':<15} {'Режим':<15} {'Операция':<10} {'Среднее время':<15}") - print("-" * 55) - for row in sorted(averaged, key=lambda x: (x[0], x[1], x[2])): - print(f"{row[0]:<15} {row[1]:<15} {row[2]:<10} {row[3]:<15.6f}") - - structures_list = ['LinkedList', 'HashTable', 'BST'] - operations_list = ['insert', 'find', 'delete'] - - fig, axes = plt.subplots(1, 3, figsize=(18, 6)) - - for i, op in enumerate(operations_list): - ax = axes[i] - x = np.arange(len(structures_list)) - width = 0.35 - - shuffled_times = [] - sorted_times = [] - - for struct in structures_list: - shuffled_times.append( - next(row[3] for row in averaged if row[0] == struct and row[1] == 'shuffled' and row[2] == op)) - sorted_times.append( - next(row[3] for row in averaged if row[0] == struct and row[1] == 'sorted' and row[2] == op)) - - bars1 = ax.bar(x - width / 2, shuffled_times, width, label='Случайный', color='#3498db') - bars2 = ax.bar(x + width / 2, sorted_times, width, label='Отсортированный', color='#e74c3c') - - for bar in bars1: - height = bar.get_height() - ax.text(bar.get_x() + bar.get_width() / 2., height + max(shuffled_times) * 0.01, - f'{height:.6f}', ha='center', va='bottom', fontsize=7) - for bar in bars2: - height = bar.get_height() - ax.text(bar.get_x() + bar.get_width() / 2., height + max(sorted_times) * 0.01, - f'{height:.6f}', ha='center', va='bottom', fontsize=7) - - ax.set_xlabel('Структура данных') - ax.set_ylabel('Время (сек)') - ax.set_title(f'Операция: {op}') - ax.set_xticks(x) - ax.set_xticklabels(structures_list) - ax.legend() - ax.grid(axis='y', alpha=0.3) - - if op == 'find': - ax.set_yscale('log') - - plt.suptitle(f'Сравнение производительности структур данных (N = {N} записей)', - fontsize=14, fontweight='bold') - plt.tight_layout() - - os.makedirs('docs', exist_ok=True) - plt.savefig('docs/benchmark_results.png', dpi=150, bbox_inches='tight') - plt.show() - print(f"График сохранён в docs/benchmark_results.png") - - print("\nАНАЛИЗ РЕЗУЛЬТАТОВ") - - print("\n1. Влияние порядка данных на BST:") - bst_shuffled_insert = next( - row[3] for row in averaged if row[0] == 'BST' and row[1] == 'shuffled' and row[2] == 'insert') - bst_sorted_insert = next( - row[3] for row in averaged if row[0] == 'BST' and row[1] == 'sorted' and row[2] == 'insert') - print(f" - Случайные данные: {bst_shuffled_insert:.6f} сек") - print(f" - Отсортированные данные: {bst_sorted_insert:.6f} сек") - if bst_shuffled_insert > 0: - print(f" - Замедление в {bst_sorted_insert / bst_shuffled_insert:.1f} раз") - print(" Причина: на отсортированных данных BST вырождается в связный список (глубина = N)") - - print("\n2. Стабильность хеш-таблицы:") - ht_shuffled = next( - row[3] for row in averaged if row[0] == 'HashTable' and row[1] == 'shuffled' and row[2] == 'insert') - ht_sorted = next(row[3] for row in averaged if row[0] == 'HashTable' and row[1] == 'sorted' and row[2] == 'insert') - print(f" - Случайные: {ht_shuffled:.6f} сек") - print(f" - Отсортированные: {ht_sorted:.6f} сек") - print(" Причина: хеш-функция равномерно распределяет ключи независимо от порядка") - - print("\n3. Медленный поиск в связном списке:") - ll_search = next(row[3] for row in averaged if row[0] == 'LinkedList' and row[1] == 'shuffled' and row[2] == 'find') - ht_search = next(row[3] for row in averaged if row[0] == 'HashTable' and row[1] == 'shuffled' and row[2] == 'find') - print(f" - LinkedList: {ll_search:.6f} сек") - print(f" - HashTable: {ht_search:.6f} сек") - if ht_search > 0: - print(f" - Хеш-таблица быстрее в {ll_search / ht_search:.1f} раз") - print(" Причина: поиск в списке всегда O(n), в хеш-таблице ~O(1)") - - print("\n4. Удаление:") - for label in ['LinkedList', 'HashTable', 'BST']: - del_shuff = next(row[3] for row in averaged if row[0] == label and row[1] == 'shuffled' and row[2] == 'delete') - del_sort = next(row[3] for row in averaged if row[0] == label and row[1] == 'sorted' and row[2] == 'delete') - print(f" - {label:15}: случ.={del_shuff:.6f} сек, отсорт.={del_sort:.6f} сек") - - print("\n5. Рекомендации:") - print(" - Частый поиск + вставки → Хеш-таблица") - print(" - Нужна сортировка «из коробки» → Сбалансированное BST (AVL/Красно-чёрное)") - print(" - Только добавление в конец → Связный список") - print(" - Обычный BST опасен на реальных частично упорядоченных данных!") - -if __name__ == '__main__': - main() \ No newline at end of file