import random import time import csv import sys sys.setrecursionlimit(10**8)#прикалюха 6 вылетаел def mk(name, phone): return {"name": name, "phone": phone} def ll_create_node(record): return [record, None] def ll_insert(ll_head, record): new_node = ll_create_node(record) new_node[1] = ll_head[0] ll_head[0] = new_node def ll_find(ll_head, name): cur = ll_head[0] while cur: if cur[0]["name"] == name: return cur[0] cur = cur[1] return None def ll_delete(ll_head, name): cur = ll_head[0] prev = None while cur: if cur[0]["name"] == name: if prev: prev[1] = cur[1] else: ll_head[0] = cur[1] return True prev = cur cur = cur[1] return False def ll_list_all(ll_head): res = [] cur = ll_head[0] while cur: res.append(cur[0]) cur = cur[1] return res def ht_hash(name, size): return hash(name) % size def ht_insert(table, record): idx = ht_hash(record["name"], len(table)) new_node = ll_create_node(record) new_node[1] = table[idx] table[idx] = new_node def ht_find(table, name): idx = ht_hash(name, len(table)) cur = table[idx] while cur: if cur[0]["name"] == name: return cur[0] cur = cur[1] return None def ht_delete(table, name): idx = ht_hash(name, len(table)) cur = table[idx] prev = None while cur: if cur[0]["name"] == name: if prev: prev[1] = cur[1] else: table[idx] = cur[1] return True prev = cur cur = cur[1] return False def ht_list_all(table): res = [] for head in table: cur = head while cur: res.append(cur[0]) cur = cur[1] return res def bst_create_node(record): return [record, None, None] def bst_insert(root, record): if root is None: return bst_create_node(record) if record["name"] < root[0]["name"]: root[1] = bst_insert(root[1], record) elif record["name"] > root[0]["name"]: root[2] = bst_insert(root[2], record) else: root[0] = record return root def bst_find(root, name): if root is None: return None if name == root[0]["name"]: return root[0] elif name < root[0]["name"]: return bst_find(root[1], name) else: return bst_find(root[2], name) def bst_find_min(node): while node[1] is not None: node = node[1] return node def bst_delete(root, name): if root is None: return None if name < root[0]["name"]: root[1] = bst_delete(root[1], name) elif name > root[0]["name"]: root[2] = bst_delete(root[2], name) else: if root[1] is None: return root[2] elif root[2] is None: return root[1] else: succ = bst_find_min(root[2]) root[0] = succ[0] root[2] = bst_delete(root[2], succ[0]["name"]) return root def bst_list_all(root): def inorder(node): if node is None: return [] return inorder(node[1]) + [node[0]] + inorder(node[2]) return inorder(root) def tmr(func): def wrapper(*args, **kwargs): start = time.perf_counter() result = func(*args, **kwargs) elapsed = time.perf_counter() - start return result, elapsed return wrapper @tmr def ins_ll(ll_head, records): for rec in records: ll_insert(ll_head, rec) @tmr def fnd_ll(ll_head, names): for name in names: ll_find(ll_head, name) @tmr def del_ll(ll_head, names): for name in names: ll_delete(ll_head, name) @tmr def ins_ht(table, records): for rec in records: ht_insert(table, rec) @tmr def fnd_ht(table, names): for name in names: ht_find(table, name) @tmr def del_ht(table, names): for name in names: ht_delete(table, name) @tmr def ins_bst(root, records): for rec in records: root = bst_insert(root, rec) return root @tmr def fnd_bst(root, names): for name in names: bst_find(root, name) @tmr def del_bst(root, names): for name in names: root = bst_delete(root, name) return root def gen(n, seed=42): random.seed(seed) recs = [] for i in range(n): name = f"user_{i:05d}" phone = random.randint(1000000, 9999999) recs.append(mk(name, phone)) return recs def prep(recs, ecnt=100, mcnt=10): alln = [r["name"] for r in recs] ex = random.sample(alln, ecnt) ms = [f"none_{i}" for i in range(mcnt)] sn = ex + ms dn = random.sample(alln, 50) return sn, dn def prm(n): if n < 2: return False if n % 2 == 0: return n == 2 d = 3 while d * d <= n: if n % d == 0: return False d += 2 return True def nxtprm(n): while not prm(n): n += 1 return n def bench(n=10000, rpts=5): recs = gen(n) shuf = recs.copy() random.shuffle(shuf) srt = sorted(recs, key=lambda r: r["name"]) snms, dnms = prep(recs) htsz = nxtprm(2 * n) exps = [ { "name": "linkedlist", "init_empty": lambda: [None], "insert": ins_ll, "find": fnd_ll, "delete": del_ll, }, { "name": "hashtable", "init_empty": lambda: [None] * htsz, "insert": ins_ht, "find": fnd_ht, "delete": del_ht, }, { "name": "bst", "init_empty": lambda: None, "insert": ins_bst, "find": fnd_bst, "delete": del_bst, }, ] res = [] for e in exps: sn = e["name"] for mn, recs_set in [("shuffled", shuf), ("sorted", srt)]: for rp in range(1, rpts + 1): st = e["init_empty"]() if sn == "bst": st, ti = e["insert"](st, recs_set) else: _, ti = e["insert"](st, recs_set) _, tf = e["find"](st, snms) if sn == "bst": st, td = e["delete"](st, dnms) else: _, td = e["delete"](st, dnms) res.append([sn, mn, "insert", rp, ti]) res.append([sn, mn, "find", rp, tf]) res.append([sn, mn, "delete", rp, td]) with open("results.csv", "w", newline="", encoding="utf-8") as f: w = csv.writer(f) w.writerow(["тип", "режим", "операция", "повтор", "время"]) w.writerows(res) from collections import defaultdict agg = defaultdict(list) for row in res: k = (row[0], row[1], row[2]) agg[k].append(row[4]) print("\n5 повторов в ср:") print(f"{'тип':<15} {'режим':<10} {'операция':<10} {'срдений':<10}") for k, times in sorted(agg.items()): avg = sum(times) / len(times) print(f"{k[0]:<15} {k[1]:<10} {k[2]:<10} {avg:<10.6f}") return res, agg def plot(agg): try: import matplotlib.pyplot as plt except ImportError: print("матплотлтб скачать") return sts = ["linkedlist", "hashtable", "bst"] mds = ["shuffled", "sorted"] ops = ["insert", "find", "delete"] fig, axes = plt.subplots(1, 3, figsize=(16, 5)) fig.suptitle("сравенние", fontsize=14) for oi, op in enumerate(ops): ax = axes[oi] data = [] for s in sts: for m in mds: k = (s, m, op) avg = sum(agg[k]) / len(agg[k]) if k in agg else 0 data.append(avg) x = range(len(sts)) width = 0.35 svals = [data[i*2] for i in range(len(sts))] svals2 = [data[i*2+1] for i in range(len(sts))] ax.bar([i - width/2 for i in x], svals, width, label='shuffled') ax.bar([i + width/2 for i in x], svals2, width, label='sorted') ax.set_xticks(x) ax.set_xticklabels(sts) ax.set_title(op) ax.set_ylabel('время (sec)') ax.legend() plt.tight_layout() plt.savefig("kortinko.png") plt.show() print("zibka kortinko.png") if __name__ == "__main__": res, agg = bench(n=10000, rpts=5) plot(agg)