import sys sys.setrecursionlimit(20000) csv_path = 'C:/Users/xalva/2026-rff_mp/stepinim/docs/data/results.csv' #Связный список def ll_insert(head, name, phone): new_node = {'name': name, 'phone': phone, 'next': None} if head is None: return new_node curr = head prev = None while curr is not None: if curr['name'] == name: curr['phone'] = phone return head prev = curr curr = curr['next'] prev['next'] = new_node 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'] return head curr = curr['next'] return head def ll_list_all(head): result = [] curr = head while curr: result.append((curr['name'], curr['phone'])) curr = curr['next'] result.sort(key=lambda x: x[0]) return result #Хэш-таблица HASH_SIZE = 1009 def _hash_name(name): return hash(name) % HASH_SIZE def ht_insert(buckets, name, phone): idx = _hash_name(name) buckets[idx] = ll_insert(buckets[idx], name, phone) def ht_find(buckets, name): idx = _hash_name(name) return ll_find(buckets[idx], name) def ht_delete(buckets, name): idx = _hash_name(name) buckets[idx] = ll_delete(buckets[idx], name) def ht_list_all(buckets): all_entries = [] for bucket in buckets: if bucket is not None: curr = bucket while curr: all_entries.append((curr['name'], curr['phone'])) curr = curr['next'] all_entries.sort(key=lambda x: x[0]) return all_entries #Двоичное дерево поиска 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']: 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: inorder(node['left']) result.append((node['name'], node['phone'])) inorder(node['right']) inorder(root) return result #ТЕСТ import random random.seed(42) N = 10000 base_records = [(f"User_{i:05d}", f"123-{i:05d}") for i in range(N)] records_shuffled = base_records.copy() random.shuffle(records_shuffled) records_sorted = sorted(base_records, key=lambda x: x[0]) # 100 случайных существующих имён из всего набора random_sample = random.sample(base_records, 100) search_existing = [name for name, _ in random_sample] # 10 несуществующих search_nonexist = [f"None_{i}" for i in range(10)] # 50 случайных для удаления delete_sample = random.sample(base_records, 50) delete_names = [name for name, _ in delete_sample] import time import csv import statistics def measure_operations(records, struct_type): results = [] for rep in range(5): if struct_type == 'll': head = None elif struct_type == 'ht': head = [None] * HASH_SIZE else: root = None start = time.perf_counter() if struct_type == 'll': for name, phone in records: head = ll_insert(head, name, phone) elif struct_type == 'ht': for name, phone in records: ht_insert(head, name, phone) else: for name, phone in records: root = bst_insert(root, name, phone) insert_time = time.perf_counter() - start results.append((rep + 1, 'insert', insert_time)) start = time.perf_counter() if struct_type == 'll': for name in search_existing + search_nonexist: ll_find(head, name) elif struct_type == 'ht': for name in search_existing + search_nonexist: ht_find(head, name) else: for name in search_existing + search_nonexist: bst_find(root, name) search_time = time.perf_counter() - start results.append((rep + 1, 'search', search_time)) start = time.perf_counter() if struct_type == 'll': for name in delete_names: head = ll_delete(head, name) elif struct_type == 'ht': for name in delete_names: ht_delete(head, name) else: for name in delete_names: root = bst_delete(root, name) delete_time = time.perf_counter() - start results.append((rep + 1, 'delete', delete_time)) return results all_data = [] for struct_name, mode_label, records in [ ("LinkedList", "shuffled", records_shuffled), ("LinkedList", "sorted", records_sorted), ("HashTable", "shuffled", records_shuffled), ("HashTable", "sorted", records_sorted), ("BST", "shuffled", records_shuffled), ("BST", "sorted", records_sorted), ]: for rep, op, t in measure_operations(records, struct_name.split('d')[0].lower()[:2] if 'Linked' in struct_name else ('ht' if 'Hash' in struct_name else 'bst')): all_data.append([struct_name, mode_label, op, f"{t:.6f}"]) with open(csv_path, 'w', newline='', encoding='utf-8') as f: writer = csv.writer(f) writer.writerow(["Структура", "Режим", "Операция", "Время (сек)"]) writer.writerows(all_data) print("CSV сохранён в docs/data/results.csv") import matplotlib.pyplot as plt import pandas as pd df = pd.read_csv(csv_path) df_avg = df.groupby(['Структура', 'Режим', 'Операция'])['Время (сек)'].mean().reset_index() fig, ax = plt.subplots(figsize=(10,6)) ops = ['insert', 'search', 'delete'] x = range(len(ops)) width = 0.12 for i, (struct, mode) in enumerate([('LinkedList','shuffled'),('LinkedList','sorted'), ('HashTable','shuffled'),('HashTable','sorted'), ('BST','shuffled'),('BST','sorted')]): subset = df_avg[(df_avg['Структура']==struct) & (df_avg['Режим']==mode)] times = [subset[subset['Операция']==op]['Время (сек)'].values[0] for op in ops] ax.bar([p + i*width for p in x], times, width, label=f"{struct} ({mode})") ax.set_xticks([p + 2.5*width for p in x]) ax.set_xticklabels(ops) ax.set_ylabel('Среднее время (сек)') ax.legend(bbox_to_anchor=(1.05, 1), loc='upper left') plt.tight_layout() plt.savefig('C:/Users/xalva/2026-rff_mp/stepinim/docs/data/grafik.png') plt.show()