[1] файл для запуска измерений

This commit is contained in:
shalovsa 2026-05-11 17:01:04 +03:00
parent 30d416cfac
commit 980da05ed5

View File

@ -0,0 +1,210 @@
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()