2026-rff_mp/stepinim/lab1_structure/test.py

255 lines
7.8 KiB
Python
Raw Normal View History

2026-04-28 18:25:45 +00:00
import sys
sys.setrecursionlimit(20000)
csv_path = 'C:/Users/xalva/2026-rff_mp/stepinim/docs/data/results.csv'
#Связный список
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
#ТЕСТ
import random
random.seed(42)
N = 10000
base_records = [(f"User_{i:05d}", f"123-{i:05d}") for i in range(N)]
records_shuffled = base_records.copy()
random.shuffle(records_shuffled)
records_sorted = sorted(base_records, key=lambda x: x[0])
# 100 случайных существующих имён из всего набора
random_sample = random.sample(base_records, 100)
search_existing = [name for name, _ in random_sample]
# 10 несуществующих
search_nonexist = [f"None_{i}" for i in range(10)]
# 50 случайных для удаления
delete_sample = random.sample(base_records, 50)
delete_names = [name for name, _ in delete_sample]
import time
import csv
import statistics
def measure_operations(records, struct_type):
results = []
for rep in range(5):
if struct_type == 'll':
head = None
elif struct_type == 'ht':
head = [None] * HASH_SIZE
else:
root = None
start = time.perf_counter()
if struct_type == 'll':
for name, phone in records:
head = ll_insert(head, name, phone)
elif struct_type == 'ht':
for name, phone in records:
ht_insert(head, name, phone)
else:
for name, phone in records:
root = bst_insert(root, name, phone)
insert_time = time.perf_counter() - start
results.append((rep + 1, 'insert', insert_time))
start = time.perf_counter()
if struct_type == 'll':
for name in search_existing + search_nonexist:
ll_find(head, name)
elif struct_type == 'ht':
for name in search_existing + search_nonexist:
ht_find(head, name)
else:
for name in search_existing + search_nonexist:
bst_find(root, name)
search_time = time.perf_counter() - start
results.append((rep + 1, 'search', search_time))
start = time.perf_counter()
if struct_type == 'll':
for name in delete_names:
head = ll_delete(head, name)
elif struct_type == 'ht':
for name in delete_names:
ht_delete(head, name)
else:
for name in delete_names:
root = bst_delete(root, name)
delete_time = time.perf_counter() - start
results.append((rep + 1, 'delete', delete_time))
return results
all_data = []
for struct_name, mode_label, records in [
("LinkedList", "shuffled", records_shuffled),
("LinkedList", "sorted", records_sorted),
("HashTable", "shuffled", records_shuffled),
("HashTable", "sorted", records_sorted),
("BST", "shuffled", records_shuffled),
("BST", "sorted", records_sorted),
]:
for rep, op, t in measure_operations(records, struct_name.split('d')[0].lower()[:2] if 'Linked' in struct_name else ('ht' if 'Hash' in struct_name else 'bst')):
all_data.append([struct_name, mode_label, op, f"{t:.6f}"])
with open(csv_path, 'w', newline='', encoding='utf-8') as f:
writer = csv.writer(f)
writer.writerow(["Структура", "Режим", "Операция", "Время (сек)"])
writer.writerows(all_data)
print("CSV сохранён в docs/data/results.csv")
import matplotlib.pyplot as plt
import pandas as pd
df = pd.read_csv(csv_path)
df_avg = df.groupby(['Структура', 'Режим', 'Операция'])['Время (сек)'].mean().reset_index()
fig, ax = plt.subplots(figsize=(10,6))
ops = ['insert', 'search', 'delete']
x = range(len(ops))
width = 0.12
for i, (struct, mode) in enumerate([('LinkedList','shuffled'),('LinkedList','sorted'),
('HashTable','shuffled'),('HashTable','sorted'),
('BST','shuffled'),('BST','sorted')]):
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])
ax.set_xticklabels(ops)
ax.set_ylabel('Среднее время (сек)')
ax.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
plt.tight_layout()
plt.savefig('C:/Users/xalva/2026-rff_mp/stepinim/docs/data/grafik.png')
plt.show()