diff --git a/SokolovEN/docs/performance_comparison.png b/SokolovEN/docs/performance_comparison.png new file mode 100644 index 0000000..b6bfdd5 Binary files /dev/null and b/SokolovEN/docs/performance_comparison.png differ diff --git a/SokolovEN/docs/results.csv b/SokolovEN/docs/results.csv new file mode 100644 index 0000000..f3d1ee9 --- /dev/null +++ b/SokolovEN/docs/results.csv @@ -0,0 +1,109 @@ +Структура,Режим,Операция,Время (сек) +LinkedList,случайный,insert,8.347676099999717 +LinkedList,случайный,find,0.057291300000088086 +LinkedList,случайный,delete,0.033828600000106235 +HashTable,случайный,insert,0.019370900000012625 +HashTable,случайный,find,0.00013010000020585721 +HashTable,случайный,delete,6.919999987076153e-05 +BST,случайный,insert,0.045051300000068295 +BST,случайный,find,0.00039449999985663453 +BST,случайный,delete,0.0002380000000812288 +LinkedList,случайный,insert,8.37124969999968 +LinkedList,случайный,find,0.05748009999979331 +LinkedList,случайный,delete,0.033760199999960605 +HashTable,случайный,insert,0.019708000000264292 +HashTable,случайный,find,0.00012689999994108803 +HashTable,случайный,delete,6.789999997636187e-05 +BST,случайный,insert,0.04297489999999016 +BST,случайный,find,0.00036730000010720687 +BST,случайный,delete,0.00021289999995133257 +LinkedList,случайный,insert,8.501181300000098 +LinkedList,случайный,find,0.06136560000004465 +LinkedList,случайный,delete,0.033985800000209565 +HashTable,случайный,insert,0.018909500000063417 +HashTable,случайный,find,0.00012770000012096716 +HashTable,случайный,delete,6.809999968027114e-05 +BST,случайный,insert,0.040991700000176934 +BST,случайный,find,0.000367999999980384 +BST,случайный,delete,0.0002165999999306223 +LinkedList,случайный,insert,8.44069300000001 +LinkedList,случайный,find,0.05868799999961993 +LinkedList,случайный,delete,0.033578099999886035 +HashTable,случайный,insert,0.017991799999890645 +HashTable,случайный,find,0.00012880000031145755 +HashTable,случайный,delete,6.720000010318472e-05 +BST,случайный,insert,0.04100620000008348 +BST,случайный,find,0.0003681999996842933 +BST,случайный,delete,0.00021289999995133257 +LinkedList,случайный,insert,8.554321999999956 +LinkedList,случайный,find,0.059801599999900645 +LinkedList,случайный,delete,0.03381919999992533 +HashTable,случайный,insert,0.01814620000004652 +HashTable,случайный,find,0.0001274000001103559 +HashTable,случайный,delete,6.649999977526022e-05 +BST,случайный,insert,0.04181910000033895 +BST,случайный,find,0.0003727000002982095 +BST,случайный,delete,0.00021440000000438886 +LinkedList,отсортированный,insert,8.395491100000072 +LinkedList,отсортированный,find,0.061166899999989255 +LinkedList,отсортированный,delete,0.03749729999981355 +HashTable,отсортированный,insert,0.08801780000021608 +HashTable,отсортированный,find,0.00013059999992037774 +HashTable,отсортированный,delete,7.719999985056347e-05 +BST,отсортированный,insert,18.99293549999993 +BST,отсортированный,find,0.17561569999998028 +BST,отсортированный,delete,0.10195840000005774 +LinkedList,отсортированный,insert,8.345957999999882 +LinkedList,отсортированный,find,0.06071609999980865 +LinkedList,отсортированный,delete,0.03802029999997103 +HashTable,отсортированный,insert,0.017803299999741284 +HashTable,отсортированный,find,0.00013059999992037774 +HashTable,отсортированный,delete,7.66999996812956e-05 +BST,отсортированный,insert,19.05815190000021 +BST,отсортированный,find,0.17255539999996472 +BST,отсортированный,delete,0.10364929999968808 +LinkedList,отсортированный,insert,8.494904799999858 +LinkedList,отсортированный,find,0.06991719999996349 +LinkedList,отсортированный,delete,0.0375927000000047 +HashTable,отсортированный,insert,0.018229599999813217 +HashTable,отсортированный,find,0.00013249999983599992 +HashTable,отсортированный,delete,8.08000004326459e-05 +BST,отсортированный,insert,19.04517390000001 +BST,отсортированный,find,0.17560349999985192 +BST,отсортированный,delete,0.10177699999985634 +LinkedList,отсортированный,insert,8.241154399999687 +LinkedList,отсортированный,find,0.08371720000013738 +LinkedList,отсортированный,delete,0.05189399999972011 +HashTable,отсортированный,insert,0.09625940000023547 +HashTable,отсортированный,find,0.0001606000000720087 +HashTable,отсортированный,delete,8.960000013757963e-05 +BST,отсортированный,insert,19.152932399999827 +BST,отсортированный,find,0.17190189999973882 +BST,отсортированный,delete,0.09978479999972478 +LinkedList,отсортированный,insert,8.261084100000062 +LinkedList,отсортированный,find,0.060434499999701075 +LinkedList,отсортированный,delete,0.03753559999995559 +HashTable,отсортированный,insert,0.018136799999865616 +HashTable,отсортированный,find,0.00013009999975110986 +HashTable,отсортированный,delete,7.819999973435188e-05 +BST,отсортированный,insert,19.379212700000153 +BST,отсортированный,find,0.17449820000001637 +BST,отсортированный,delete,0.0995044000001144 +LinkedList,случайный,insert (СРЕДНЕЕ),8.443024419999892 +LinkedList,случайный,find (СРЕДНЕЕ),0.05892531999988933 +LinkedList,случайный,delete (СРЕДНЕЕ),0.033794380000017554 +LinkedList,отсортированный,insert (СРЕДНЕЕ),8.347718479999912 +LinkedList,отсортированный,find (СРЕДНЕЕ),0.06719037999991997 +LinkedList,отсортированный,delete (СРЕДНЕЕ),0.040507979999892994 +HashTable,случайный,insert (СРЕДНЕЕ),0.0188252800000555 +HashTable,случайный,find (СРЕДНЕЕ),0.00012818000013794517 +HashTable,случайный,delete (СРЕДНЕЕ),6.77799998811679e-05 +HashTable,отсортированный,insert (СРЕДНЕЕ),0.047689379999974336 +HashTable,отсортированный,find (СРЕДНЕЕ),0.0001368799998999748 +HashTable,отсортированный,delete (СРЕДНЕЕ),8.04999999672873e-05 +BST,случайный,insert (СРЕДНЕЕ),0.04236864000013156 +BST,случайный,find (СРЕДНЕЕ),0.0003741399999853456 +BST,случайный,delete (СРЕДНЕЕ),0.00021895999998378102 +BST,отсортированный,insert (СРЕДНЕЕ),19.125681280000027 +BST,отсортированный,find (СРЕДНЕЕ),0.17403493999991043 +BST,отсортированный,delete (СРЕДНЕЕ),0.10133477999988827 diff --git a/SokolovEN/docs/СтруктурыДанных.py b/SokolovEN/docs/СтруктурыДанных.py new file mode 100644 index 0000000..1eaa7dd --- /dev/null +++ b/SokolovEN/docs/СтруктурыДанных.py @@ -0,0 +1,257 @@ +import random +import time +import csv +import sys + + +sys.setrecursionlimit(20000) + + +# 1. СВЯЗНЫЙ СПИСОК +def ll_insert(head, name, phone): + curr = head + while curr: + if curr['name'] == name: + curr['phone'] = phone + return head + curr = curr['next'] + + new_node = {'name': name, 'phone': phone, 'next': None} + if head is None: + return new_node + + curr = head + while curr['next']: + curr = curr['next'] + curr['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): + res = [] + curr = head + while curr: + res.append((curr['name'], curr['phone'])) + curr = curr['next'] + res.sort(key=lambda x: x[0]) + return res + + + +# 2. ХЕШ-ТАБЛИЦА +BUCKET_COUNT = 1024 + + +def ht_insert(buckets, name, phone): + idx = hash(name) % BUCKET_COUNT + buckets[idx] = ll_insert(buckets[idx], name, phone) + + +def ht_find(buckets, name): + idx = hash(name) % BUCKET_COUNT + return ll_find(buckets[idx], name) + + +def ht_delete(buckets, name): + idx = hash(name) % BUCKET_COUNT + buckets[idx] = ll_delete(buckets[idx], name) + + +def ht_list_all(buckets): + res = [] + for head in buckets: + curr = head + while curr: + res.append((curr['name'], curr['phone'])) + curr = curr['next'] + res.sort(key=lambda x: x[0]) + return res + + + +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): + if root is None: + return None + if name == root['name']: + return root['phone'] + elif name < root['name']: + return bst_find(root['left'], name) + else: + return bst_find(root['right'], name) + + +def _bst_find_min(node): + curr = node + while curr['left'] is not None: + curr = curr['left'] + return curr + + +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: + successor = _bst_find_min(root['right']) + root['name'] = successor['name'] + root['phone'] = successor['phone'] + root['right'] = bst_delete(root['right'], successor['name']) + return root + + +def bst_list_all(root): + res = [] + + def inorder(node): + if node: + inorder(node['left']) + res.append((node['name'], node['phone'])) + inorder(node['right']) + + inorder(root) + return res + + + +# ЭКСПЕРИМЕНТАЛЬНАЯ ЧАСТЬ +def run_experiments(): + N = 10000 + base_records = [(f"User_{i:05d}", f"100{i:05d}") for i in range(N)] + + records_sorted = sorted(base_records, key=lambda x: x[0]) + records_shuffled = base_records[:] + random.shuffle(records_shuffled) + + all_names = [r[0] for r in base_records] + find_existing = random.sample(all_names, 100) + find_non_existing = [f"Missing_{i}" for i in range(10)] + delete_targets = random.sample(all_names, 50) + + all_results = [] + structures = ["LinkedList", "HashTable", "BST"] + data_modes = [("случайный", records_shuffled), ("отсортированный", records_sorted)] + + for mode_name, records in data_modes: + print(f"\n Режим: {mode_name}") + for run in range(1, 6): + print(f" запуск {run}/5") + + + head = None + t = time.perf_counter() + for n, p in records: head = ll_insert(head, n, p) + t_ins = time.perf_counter() - t + + t = time.perf_counter() + for n in find_existing + find_non_existing: ll_find(head, n) + t_find = time.perf_counter() - t + + t = time.perf_counter() + for n in delete_targets: head = ll_delete(head, n) + t_del = time.perf_counter() - t + + all_results.append(["LinkedList", mode_name, "insert", t_ins]) + all_results.append(["LinkedList", mode_name, "find", t_find]) + all_results.append(["LinkedList", mode_name, "delete", t_del]) + + + buckets = [None] * BUCKET_COUNT + t = time.perf_counter() + for n, p in records: ht_insert(buckets, n, p) + t_ins = time.perf_counter() - t + + t = time.perf_counter() + for n in find_existing + find_non_existing: ht_find(buckets, n) + t_find = time.perf_counter() - t + + t = time.perf_counter() + for n in delete_targets: ht_delete(buckets, n) + t_del = time.perf_counter() - t + + all_results.append(["HashTable", mode_name, "insert", t_ins]) + all_results.append(["HashTable", mode_name, "find", t_find]) + all_results.append(["HashTable", mode_name, "delete", t_del]) + + + root = None + t = time.perf_counter() + for n, p in records: root = bst_insert(root, n, p) + t_ins = time.perf_counter() - t + + t = time.perf_counter() + for n in find_existing + find_non_existing: bst_find(root, n) + t_find = time.perf_counter() - t + + t = time.perf_counter() + for n in delete_targets: root = bst_delete(root, n) + t_del = time.perf_counter() - t + + all_results.append(["BST", mode_name, "insert", t_ins]) + all_results.append(["BST", mode_name, "find", t_find]) + all_results.append(["BST", mode_name, "delete", t_del]) + + + averages = [] + for struct in structures: + for mode in ["случайный", "отсортированный"]: + for op in ["insert", "find", "delete"]: + times = [r[3] for r in all_results if r[0] == struct and r[1] == mode and r[2] == op] + avg = sum(times) / len(times) + averages.append([struct, mode, f"{op} (СРЕДНЕЕ)", avg]) + + final_csv_data = [["Структура", "Режим", "Операция", "Время (сек)"]] + all_results + averages + + with open("results.csv", "w", newline="", encoding="utf-8-sig") as f: + writer = csv.writer(f) + writer.writerows(final_csv_data) + + return all_results, averages + + +if __name__ == "__main__": + raw_data, avg_data = run_experiments() + diff --git a/SokolovEN/docs/графики.py b/SokolovEN/docs/графики.py new file mode 100644 index 0000000..bf836a2 --- /dev/null +++ b/SokolovEN/docs/графики.py @@ -0,0 +1,35 @@ +import pandas as pd +import matplotlib.pyplot as plt +import numpy as np + +df = pd.read_csv("results.csv", encoding="utf-8-sig") +df_avg = df[df["Операция"].str.contains("СРЕДНЕЕ")].copy() +df_avg["Операция"] = df_avg["Операция"].str.replace(" (СРЕДНЕЕ)", "") + +modes = ["случайный", "отсортированный"] +operations = ["insert", "find", "delete"] +structures = ["LinkedList", "HashTable", "BST"] + +x = np.arange(len(structures)) +width = 0.35 + +fig, axes = plt.subplots(1, 3, figsize=(18, 5)) + +for i, op in enumerate(operations): + ax = axes[i] + for j, mode in enumerate(modes): + mask = (df_avg["Операция"] == op) & (df_avg["Режим"] == mode) + times = df_avg[mask]["Время (сек)"].values + label = "Случайные данные" if mode == "случайный" else "Отсортированные данные" + ax.bar(x + j * width, times, width, label=label) + + ax.set_title(f"Операция: {op.upper()}") + ax.set_xticks(x + width / 2) + ax.set_xticklabels(structures) + ax.set_ylabel("Время (сек)") + ax.legend() + ax.grid(axis="y", linestyle="--", alpha=0.7) + +plt.tight_layout() +plt.savefig("performance_comparison.png", dpi=300) +plt.show() \ No newline at end of file