2026-rff_mp/kornevma/docs/1/main.py
2026-05-20 20:13:04 +03:00

349 lines
8.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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)