import random as rnd import time import csv # СВЯЗНЫЙ СПИСОК def ll_insert(head, name, phone): new_node = {'name': name, 'phone': phone, 'next': None} if head is None: return new_node current = head while current is not None: if current['name'] == name: current['phone'] = phone return head if current['next'] is None: break 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 sort_records(lst): n = len(lst) for i in range(n): for j in range(0, n-i-1): if lst[j][0] > lst[j + 1][0]: lst[j], lst[j + 1] = lst[j + 1], lst[j] return lst def ll_list_all(head): record = [] current = head while current is not None: record += [(current['name'], current['phone'])] current = current['next'] res = sort_records(record) return res # ХЕШ-ТАБЛИЦА def def_hash(name, size): hash_value = 0 for char in name: hash_value += ord(char) final_idx = hash_value % size return final_idx def ht_insert(buckets, name, phone): size = len(buckets) idx = def_hash(name, size) buckets[idx] = ll_insert(buckets[idx], name, phone) return buckets def ht_find(buckets, name): size = len(buckets) idx = def_hash(name, size) return ll_find(buckets[idx], name) def ht_delete(buckets, name): size = len(buckets) idx = def_hash(name, size) buckets[idx] = ll_delete(buckets[idx], name) return buckets def ht_list_all(buckets): res = [] for head in buckets: current = head while current is not None: res += [(current['name'], current['phone'])] current = current['next'] return sort_records(res) # ДВОИЧНОЕ ДЕРЕВО ПОИСКА 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']: current['phone'] = phone break elif name < current['name']: if current['left'] is None: current['left'] = new_node break current = current['left'] else: if current['right'] is None: current['right'] = new_node break current = current['right'] 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 p_node = None current = root while current is not None and current['name'] != name: p_node = current if name < current['name']: current = current['left'] else: current = current['right'] if current is None: return root if current['left'] is None and current['right'] is None: if p_node is None: return None if p_node['left'] is current: p_node['left'] = None else: p_node['right'] = None return root if current['left'] is None: c_node = current['right'] elif current['right'] is None: c_node = current['left'] else: succ_parent = current succ = current['right'] while succ['left']: succ_parent = succ succ = succ['left'] current['name'], current['phone'] = succ['name'], succ['phone'] if succ_parent['left'] is succ: succ_parent['left'] = succ['right'] else: succ_parent['right'] = succ['right'] return root if p_node is None: return c_node if p_node['left'] is current: p_node['left'] = c_node else: p_node['right'] = c_node return root def bst_list_all(root): record = [] def helper(node): if node is not None: helper(node['left']) nonlocal record record += [(node['name'], node['phone'])] helper(node['right']) helper(root) return record # ЭКСПЕРИМЕНТАЛЬНАЯ ЧАСТЬ if __name__ == '__main__': N = 10000 records = [] for i in range(N): name = f"User_{i:05d}" phone = f"+7-{rnd.randint(100, 999)}-{rnd.randint(100, 999)}-{rnd.randint(1000, 9999)}" records.append((name, phone)) records_shuffled = records[:] rnd.shuffle(records_shuffled) records_sorted = sorted(records, key=lambda x: x[0]) s_names = [] for i in range(100): s_names.append(records_shuffled[i][0]) for i in range(10): s_names.append(f"None_{i}") d_names = [] sampled = rnd.sample(records_shuffled, 50) for item in sampled: d_names.append(item[0]) print("Начало замеров...") results = [["Структура", "Режим", "Операция", "Время (сек)"]] # ПРОВЕДЕНИЕ ЗАМЕРОВ # СВЯЗНЫЙ СПИСОК for mode_name, data in [("случайный", records_shuffled), ("отсортированный", records_sorted)]: s_ins = 0 s_fnd=0 s_del=0 for _ in range(5): ll = None t1 = time.perf_counter() for name, phone in data: ll = ll_insert(ll, name, phone) time_ins = time.perf_counter() - t1 s_ins += time_ins results.append(["LinkedList", mode_name, "вставка", time_ins]) t1 = time.perf_counter() for name in s_names: ll_find(ll, name) time_fnd = time.perf_counter() - t1 s_fnd += time_fnd results.append(["LinkedList", mode_name, "поиск", time_fnd]) t1 = time.perf_counter() for name in d_names: ll = ll_delete(ll, name) time_del = time.perf_counter() - t1 s_del += time_del results.append(["LinkedList", mode_name, "удаление", time_del]) print(f" Связный список ({mode_name}) | Среднее за 5 замеров ") print(f"Вставка: {s_ins/5:.5f} сек.") print(f"Поиск: {s_fnd/5:.5f} сек.") print(f"Удаление: {s_del/5:.5f} сек.") print("-" * 40) # ХЕШ-ТАБЛИЦА for mode_name, data in [("случайный", records_shuffled), ("отсортированный", records_sorted)]: s_ins = 0 s_fnd=0 s_del =0 for _ in range(5): ht = [None] * 2000 t1 = time.perf_counter() for name, phone in data: ht = ht_insert(ht, name, phone) time_ins = time.perf_counter() - t1 s_ins += time_ins results.append(["HashTable", mode_name, "вставка", time_ins]) t1 = time.perf_counter() for name in s_names: ht_find(ht, name) time_fnd = time.perf_counter() - t1 s_fnd += time_fnd results.append(["HashTable", mode_name, "поиск", time_fnd]) t1 = time.perf_counter() for name in d_names: ht = ht_delete(ht, name) time_del = time.perf_counter() - t1 s_del += time_del results.append(["HashTable", mode_name, "удаление", time_del]) print(f" Хеш-таблица ({mode_name}) | Среднее за 5 замеров ") print(f"Вставка: {s_ins/5:.5f} сек.") print(f"Поиск: {s_fnd/5:.5f} сек.") print(f"Удаление: {s_del/5:.5f} сек.") print("-" * 40) # ДЕРЕВО for mode_name, data in [("случайный", records_shuffled), ("отсортированный", records_sorted)]: s_ins = 0 s_fnd = 0 s_del = 0 for _ in range(5): bst = None t1 = time.perf_counter() for name, phone in data: bst = bst_insert(bst, name, phone) time_ins = time.perf_counter() - t1 s_ins += time_ins results.append(["BST", mode_name, "вставка", time_ins]) t1 = time.perf_counter() for name in s_names: bst_find(bst, name) time_fnd = time.perf_counter() - t1 s_fnd += time_fnd results.append(["BST", mode_name, "поиск", time_fnd]) t1 = time.perf_counter() for name in d_names: bst = bst_delete(bst, name) time_del = time.perf_counter() - t1 s_del += time_del results.append(["BST", mode_name, "удаление", time_del]) print(f"Двоичное дерево ({mode_name}) | Среднее за 5 замеров ") print(f"Вставка: {s_ins/5:.5f} сек.") print(f"Поиск: {s_fnd/5:.5f} сек.") print(f"Удаление: {s_del/5:.5f} сек.") print("-" * 40) # Сохранение результатов with open("docs/data/results.csv", "w", newline="", encoding="utf-8") as f: writer = csv.writer(f) writer.writerows(results)