2026-rff_mp/kornevma/docs/1/main.py

349 lines
8.3 KiB
Python
Raw Normal View History

2026-05-20 17:13:04 +00:00
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)