2026-rff_mp/stepinim/lab1_structure/test.py
2026-04-28 21:25:45 +03:00

255 lines
7.8 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 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()