2026-rff_mp/stepinim/lab1_structure/test.py

433 lines
10 KiB
Python
Raw Normal View History

2026-04-28 18:25:45 +00:00
import sys
2026-05-20 12:19:09 +00:00
sys.setrecursionlimit(30000)
2026-04-28 18:25:45 +00:00
2026-05-20 12:19:09 +00:00
csv_path = '/stepinim/docs/data/lab1_results.csv'
2026-04-28 18:25:45 +00:00
#Связный список
def ll_insert(head, name, phone):
new_node = {'name': name, 'phone': phone, 'next': None}
if head is None:
return new_node
curr = head
prev = None
while curr is not None:
if curr['name'] == name:
curr['phone'] = phone
return head
prev = curr
curr = curr['next']
prev['next'] = new_node
return head
def ll_find(head, name):
curr = head
while curr:
if curr['name'] == name:
return curr['phone']
curr = curr['next']
return None
def ll_delete(head, name):
if head is None:
return None
if head['name'] == name:
return head['next']
curr = head
while curr['next']:
if curr['next']['name'] == name:
curr['next'] = curr['next']['next']
return head
curr = curr['next']
return head
def ll_list_all(head):
result = []
curr = head
while curr:
result.append((curr['name'], curr['phone']))
curr = curr['next']
result.sort(key=lambda x: x[0])
return result
#Хэш-таблица
HASH_SIZE = 1009
def _hash_name(name):
return hash(name) % HASH_SIZE
def ht_insert(buckets, name, phone):
idx = _hash_name(name)
buckets[idx] = ll_insert(buckets[idx], name, phone)
def ht_find(buckets, name):
idx = _hash_name(name)
return ll_find(buckets[idx], name)
def ht_delete(buckets, name):
idx = _hash_name(name)
buckets[idx] = ll_delete(buckets[idx], name)
def ht_list_all(buckets):
all_entries = []
for bucket in buckets:
if bucket is not None:
curr = bucket
while curr:
all_entries.append((curr['name'], curr['phone']))
curr = curr['next']
all_entries.sort(key=lambda x: x[0])
return all_entries
#Двоичное дерево поиска
def bst_insert(root, name, phone):
if root is None:
return {'name': name, 'phone': phone, 'left': None, 'right': None}
if name < root['name']:
root['left'] = bst_insert(root['left'], name, phone)
elif name > root['name']:
root['right'] = bst_insert(root['right'], name, phone)
else:
root['phone'] = phone
return root
def bst_find(root, name):
curr = root
while curr:
if name == curr['name']:
return curr['phone']
elif name < curr['name']:
curr = curr['left']
else:
curr = curr['right']
return None
def bst_delete(root, name):
if root is None:
return None
if name < root['name']:
root['left'] = bst_delete(root['left'], name)
elif name > root['name']:
root['right'] = bst_delete(root['right'], name)
else:
if root['left'] is None:
return root['right']
if root['right'] is None:
return root['left']
min_node = root['right']
while min_node['left']:
min_node = min_node['left']
root['name'] = min_node['name']
root['phone'] = min_node['phone']
root['right'] = bst_delete(root['right'], min_node['name'])
return root
def bst_list_all(root):
result = []
def inorder(node):
if node:
inorder(node['left'])
result.append((node['name'], node['phone']))
inorder(node['right'])
inorder(root)
return result
2026-05-20 12:19:09 +00:00
# ============================================================
# TECT
# ============================================================
import os
2026-04-28 18:25:45 +00:00
import random
2026-05-20 12:19:09 +00:00
import time
import csv
import pandas as pd
import matplotlib.pyplot as plt
# ============================================================
# ПОДГОТОВКА ПАПОК
# ============================================================
DATA_DIR = os.path.join("docs", "data")
os.makedirs(DATA_DIR, exist_ok=True)
csv_path = os.path.join(DATA_DIR, "lab1_results.csv")
graph_path = os.path.join(DATA_DIR, "lab1_graph.png")
# ============================================================
# ТЕСТОВЫЕ ДАННЫЕ
# ============================================================
2026-04-28 18:25:45 +00:00
random.seed(42)
2026-05-20 12:19:09 +00:00
N = 3000
base_records = [
(f"User_{i:05d}", f"123-{i:05d}")
for i in range(N)
]
2026-04-28 18:25:45 +00:00
records_shuffled = base_records.copy()
random.shuffle(records_shuffled)
2026-05-20 12:19:09 +00:00
2026-04-28 18:25:45 +00:00
records_sorted = sorted(base_records, key=lambda x: x[0])
2026-05-20 12:19:09 +00:00
# Поиск
search_existing = [
name for name, _ in random.sample(base_records, 100)
]
2026-04-28 18:25:45 +00:00
2026-05-20 12:19:09 +00:00
search_nonexist = [
f"None_{i}"
for i in range(10)
]
2026-04-28 18:25:45 +00:00
2026-05-20 12:19:09 +00:00
# Удаление
delete_names = [
name for name, _ in random.sample(base_records, 50)
]
2026-04-28 18:25:45 +00:00
2026-05-20 12:19:09 +00:00
# ============================================================
# СОЗДАНИЕ СТРУКТУР
# ============================================================
def build_structure(records, struct_type):
if struct_type == "ll":
structure = None
for name, phone in records:
structure = ll_insert(structure, name, phone)
return structure
elif struct_type == "ht":
structure = [None] * HASH_SIZE
for name, phone in records:
ht_insert(structure, name, phone)
return structure
elif struct_type == "bst":
structure = None
for name, phone in records:
structure = bst_insert(structure, name, phone)
return structure
# ============================================================
# INSERT
# ============================================================
def measure_insert(records, struct_type):
start = time.perf_counter()
build_structure(records, struct_type)
end = time.perf_counter()
return end - start
# ============================================================
# SEARCH
# ============================================================
def measure_search(records, struct_type):
structure = build_structure(records, struct_type)
start = time.perf_counter()
if struct_type == "ll":
for name in search_existing + search_nonexist:
ll_find(structure, name)
elif struct_type == "ht":
for name in search_existing + search_nonexist:
ht_find(structure, name)
elif struct_type == "bst":
for name in search_existing + search_nonexist:
bst_find(structure, name)
end = time.perf_counter()
return end - start
# ============================================================
# DELETE
# ============================================================
def measure_delete(records, struct_type):
structure = build_structure(records, struct_type)
start = time.perf_counter()
if struct_type == "ll":
for name in delete_names:
structure = ll_delete(structure, name)
elif struct_type == "ht":
for name in delete_names:
ht_delete(structure, name)
elif struct_type == "bst":
for name in delete_names:
structure = bst_delete(structure, name)
end = time.perf_counter()
return end - start
# ============================================================
# ЗАМЕРЫ
# ============================================================
2026-04-28 18:25:45 +00:00
all_data = []
2026-05-20 12:19:09 +00:00
experiments = [
("LinkedList", "ll"),
("HashTable", "ht"),
("BST", "bst")
]
modes = [
("shuffled", records_shuffled),
("sorted", records_sorted)
]
for struct_name, struct_type in experiments:
for mode_name, records in modes:
for rep in range(1, 4):
2026-04-28 18:25:45 +00:00
2026-05-20 12:19:09 +00:00
insert_time = measure_insert(records, struct_type)
search_time = measure_search(records, struct_type)
delete_time = measure_delete(records, struct_type)
all_data.append([
struct_name,
mode_name,
rep,
"insert",
insert_time
])
all_data.append([
struct_name,
mode_name,
rep,
"search",
search_time
])
all_data.append([
struct_name,
mode_name,
rep,
"delete",
delete_time
])
# ============================================================
# CSV
# ============================================================
with open(csv_path, "w", newline="", encoding="utf-8") as f:
2026-04-28 18:25:45 +00:00
writer = csv.writer(f)
2026-05-20 12:19:09 +00:00
writer.writerow([
"Структура",
"Режим",
"Повтор",
"Операция",
"Время (сек)"
])
2026-04-28 18:25:45 +00:00
2026-05-20 12:19:09 +00:00
writer.writerows(all_data)
2026-04-28 18:25:45 +00:00
2026-05-20 12:19:09 +00:00
print(f"CSV сохранён: {csv_path}")
2026-04-28 18:25:45 +00:00
2026-05-20 12:19:09 +00:00
# ============================================================
# ГРАФИК
# ============================================================
2026-04-28 18:25:45 +00:00
df = pd.read_csv(csv_path)
2026-05-20 12:19:09 +00:00
df_avg = (
df.groupby(
["Структура", "Режим", "Операция"]
)["Время (сек)"]
.mean()
.reset_index()
)
fig, ax = plt.subplots(figsize=(12, 6))
ops = ["insert", "search", "delete"]
2026-04-28 18:25:45 +00:00
x = range(len(ops))
2026-05-20 12:19:09 +00:00
2026-04-28 18:25:45 +00:00
width = 0.12
2026-05-20 12:19:09 +00:00
configs = [
("LinkedList", "shuffled"),
("LinkedList", "sorted"),
("HashTable", "shuffled"),
("HashTable", "sorted"),
("BST", "shuffled"),
("BST", "sorted")
]
for i, (struct, mode) in enumerate(configs):
subset = df_avg[
(df_avg["Структура"] == struct)
&
(df_avg["Режим"] == mode)
]
times = [
subset[
subset["Операция"] == op
]["Время (сек)"].values[0]
for op in ops
]
ax.bar(
[p + i * width for p in x],
times,
width,
label=f"{struct} ({mode})"
)
ax.set_xticks([p + 2.5 * width for p in x])
2026-04-28 18:25:45 +00:00
ax.set_xticklabels(ops)
2026-05-20 12:19:09 +00:00
ax.set_ylabel("Среднее время (сек)")
ax.set_title("Сравнение структур данных")
ax.legend(
bbox_to_anchor=(1.05, 1),
loc="upper left"
)
2026-04-28 18:25:45 +00:00
plt.tight_layout()
2026-05-20 12:19:09 +00:00
plt.savefig(graph_path)
print(f"График сохранён: {graph_path}")
2026-04-28 18:25:45 +00:00
plt.show()