2026-rff_mp/shalovsa/lab1/docs/data/laba.py

211 lines
6.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 time
import random
import csv
import os
from phone_book import (
ll_insert, ll_find, ll_delete, ll_list_all,
ht_make, ht_insert, ht_find, ht_delete, ht_list_all,
bst_insert, bst_find, bst_delete, bst_list_all,
)
N = 10_000
REPEATS = 5
SEARCH_COUNT = 110
DELETE_COUNT = 50
HT_SIZE = 256
RANDOM_SEED = 42
random.seed(RANDOM_SEED)
OUTPUT_DIR = os.path.dirname(__file__)
os.makedirs(OUTPUT_DIR, exist_ok=True)
CSV_PATH = os.path.join(OUTPUT_DIR, 'results.csv')
def generate_records(n):
records = [(f"User_{i:05d}", f"+7{random.randint(1000000000, 9999999999)}")
for i in range(n)]
return records
records_base = generate_records(N)
records_shuffled = records_base[:]
random.shuffle(records_shuffled)
records_sorted = sorted(records_base, key=lambda x: x[0])
existing_names = [r[0] for r in random.sample(records_base, 100)]
missing_names = [f"None_{i}" for i in range(10)]
search_names = existing_names + missing_names
delete_names = [r[0] for r in random.sample(records_base, DELETE_COUNT)]
def measure(func, *args, **kwargs):
start = time.perf_counter()
result = func(*args, **kwargs)
end = time.perf_counter()
return end - start, result
def bench_linked_list(records, mode_label):
times = {'insert': [], 'find': [], 'delete': []}
for _ in range(REPEATS):
head = None
t_start = time.perf_counter()
for name, phone in records:
head = ll_insert(head, name, phone)
times['insert'].append(time.perf_counter() - t_start)
t_start = time.perf_counter()
for name in search_names:
ll_find(head, name)
times['find'].append(time.perf_counter() - t_start)
t_start = time.perf_counter()
for name in delete_names:
head = ll_delete(head, name)
times['delete'].append(time.perf_counter() - t_start)
return times
def bench_hash_table(records, mode_label):
times = {'insert': [], 'find': [], 'delete': []}
for _ in range(REPEATS):
buckets = ht_make(HT_SIZE)
t_start = time.perf_counter()
for name, phone in records:
ht_insert(buckets, name, phone)
times['insert'].append(time.perf_counter() - t_start)
t_start = time.perf_counter()
for name in search_names:
ht_find(buckets, name)
times['find'].append(time.perf_counter() - t_start)
t_start = time.perf_counter()
for name in delete_names:
ht_delete(buckets, name)
times['delete'].append(time.perf_counter() - t_start)
return times
def bench_bst(records, mode_label):
times = {'insert': [], 'find': [], 'delete': []}
for _ in range(REPEATS):
root = None
t_start = time.perf_counter()
for name, phone in records:
root = bst_insert(root, name, phone)
times['insert'].append(time.perf_counter() - t_start)
t_start = time.perf_counter()
for name in search_names:
bst_find(root, name)
times['find'].append(time.perf_counter() - t_start)
t_start = time.perf_counter()
for name in delete_names:
root = bst_delete(root, name)
times['delete'].append(time.perf_counter() - t_start)
return times
def avg(lst):
return sum(lst) / len(lst)
def run_all():
print(f"Запуск: N={N}, повторений={REPEATS}\n")
print(f"{'Структура':<15} {'Режим':<12} {'Операция':<10} "
f"{'Среднее (с)':<14} {'Все замеры'}")
print("-" * 80)
all_results = [["Структура", "Режим", "Операция", "Среднее (с)"] +
[f"Замер_{i+1}" for i in range(REPEATS)]]
datasets = [
(records_shuffled, "случайный"),
(records_sorted, "сортированный"),
]
benchmarks = [
("LinkedList", bench_linked_list),
("HashTable", bench_hash_table),
("BST", bench_bst),
]
for ds_records, ds_mode in datasets:
for struct_name, bench_func in benchmarks:
print(f"\n [{struct_name}] режим: {ds_mode}")
if struct_name == "BST" and ds_mode == "сортированный":
import sys
sys.setrecursionlimit(50_000)
times = bench_func(ds_records, ds_mode)
for op, op_times in times.items():
mean = avg(op_times)
row = [struct_name, ds_mode, op, f"{mean:.6f}"] + \
[f"{t:.6f}" for t in op_times]
all_results.append(row)
print(f" {op:<10} среднее={mean:.6f}с "
f"замеры={[f'{t:.4f}' for t in op_times]}")
with open(CSV_PATH, 'w', newline='', encoding='utf-8') as f:
writer = csv.writer(f)
writer.writerows(all_results)
print(f"\n✅ Результаты сохранены в: {CSV_PATH}")
return all_results
def smoke_test():
print("=== Smoke Test ===\n")
test_data = [("Alice", "111"), ("Bob", "222"), ("Charlie", "333")]
head = None
for name, phone in test_data:
head = ll_insert(head, name, phone)
assert ll_find(head, "Alice") == "111"
assert ll_find(head, "Bob") == "222"
assert ll_find(head, "Nobody") is None
head = ll_delete(head, "Bob")
assert ll_find(head, "Bob") is None
sorted_ll = ll_list_all(head)
assert sorted_ll == [("Alice", "111"), ("Charlie", "333")]
print("✅ LinkedList — OK")
buckets = ht_make(16)
for name, phone in test_data:
ht_insert(buckets, name, phone)
assert ht_find(buckets, "Charlie") == "333"
assert ht_find(buckets, "Nobody") is None
ht_delete(buckets, "Alice")
assert ht_find(buckets, "Alice") is None
sorted_ht = ht_list_all(buckets)
assert sorted_ht == [("Bob", "222"), ("Charlie", "333")]
print("✅ HashTable — OK")
root = None
for name, phone in test_data:
root = bst_insert(root, name, phone)
assert bst_find(root, "Alice") == "111"
assert bst_find(root, "Nobody") is None
root = bst_delete(root, "Alice")
assert bst_find(root, "Alice") is None
sorted_bst = bst_list_all(root)
assert sorted_bst == [("Bob", "222"), ("Charlie", "333")]
print("✅ BST — OK")
print("\nВсе тесты пройдены!\n")
if __name__ == "__main__":
smoke_test()
results = run_all()