2026-rff_mp/ShulpinIN/datastructure_lab1/datastruct.py

308 lines
9.0 KiB
Python
Raw Normal View History

import random
import time
import csv
import os
import matplotlib.pyplot as plt
import numpy as np
from sys import setrecursionlimit
setrecursionlimit(20000)
def ll_insert(head, name, phone):
new_node = {'name': name, 'phone': phone, 'next': None}
if head is None:
return new_node
current = head
while current:
if current['name'] == name:
current['phone'] = phone
return head
if current['next'] is None:
break
current = current['next']
current['next'] = new_node
return head
def ll_find(head, name):
current = head
while current:
if current['name'] == name:
return current['phone']
current = current['next']
return None
def ll_delete(head, name):
if head is None:
return None
if head['name'] == name:
return head['next']
prev = head
current = head['next']
while current:
if current['name'] == name:
prev['next'] = current['next']
return head
prev = current
current = current['next']
return head
def ll_list_all(head):
records = []
current = head
while current:
records.append((current['name'], current['phone']))
current = current['next']
records.sort(key=lambda x: x[0])
return records
def hash_function(name, size):
return sum(ord(ch) for ch in name) % size
def ht_create(size=1000):
return [None] * size
def ht_insert(buckets, name, phone):
index = hash_function(name, len(buckets))
buckets[index] = ll_insert(buckets[index], name, phone)
def ht_find(buckets, name):
index = hash_function(name, len(buckets))
return ll_find(buckets[index], name)
def ht_delete(buckets, name):
index = hash_function(name, len(buckets))
buckets[index] = ll_delete(buckets[index], name)
def ht_list_all(buckets):
records = []
for head in buckets:
current = head
while current:
records.append((current['name'], current['phone']))
current = current['next']
records.sort(key=lambda x: x[0])
return records
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):
if root is None:
return None
if name == root['name']:
return root['phone']
elif name < root['name']:
return bst_find(root['left'], name)
else:
return bst_find(root['right'], name)
def bst_min_node(node):
current = node
while current and current['left']:
current = current['left']
return current
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']
elif root['right'] is None:
return root['left']
temp = bst_min_node(root['right'])
root['name'] = temp['name']
root['phone'] = temp['phone']
root['right'] = bst_delete(root['right'], temp['name'])
return root
def bst_list_all(root, result=None):
if result is None:
result = []
if root:
bst_list_all(root['left'], result)
result.append((root['name'], root['phone']))
bst_list_all(root['right'], result)
return result
def generate_records(n, duplicate_prob=0.1):
records = []
for i in range(n):
if random.random() < duplicate_prob and i > 0:
name = records[random.randint(0, i - 1)][0]
else:
name = f"User_{random.randint(0, n * 2)}"
phone = f"+7-999-{random.randint(1000000, 9999999)}"
records.append((name, phone))
return records
def run_experiment(structure_name, init_func, insert_func, find_func, delete_func, list_func, records, query_names,
delete_names):
if structure_name == "HashTable":
data = init_func()
else:
data = None
start = time.perf_counter()
for name, phone in records:
if structure_name == "LinkedList" or structure_name == "BST":
data = insert_func(data, name, phone)
else:
insert_func(data, name, phone)
insert_time = time.perf_counter() - start
start = time.perf_counter()
for name in query_names:
find_func(data, name)
find_time = time.perf_counter() - start
start = time.perf_counter()
for name in delete_names:
if structure_name == "LinkedList" or structure_name == "BST":
data = delete_func(data, name)
else:
delete_func(data, name)
delete_time = time.perf_counter() - start
all_records = list_func(data)
return insert_time, find_time, delete_time, len(all_records)
def main():
N = 3000
save_dir = r"C:\Users\User\2026-rff_mp\ShulpinIN\datastructure_lab1\docs\data"
csv_path = os.path.join(save_dir, "results.csv")
graph_path = os.path.join(save_dir, "performance_comparison.png")
records_original = generate_records(N, duplicate_prob=0.05)
records_shuffled = records_original.copy()
random.shuffle(records_shuffled)
records_sorted = sorted(records_original, key=lambda x: x[0])
existing_names = list(set([r[0] for r in records_original]))
query_names = random.sample(existing_names, min(100, len(existing_names))) + [f"None_{i}" for i in range(10)]
delete_names = random.sample(existing_names, min(50, len(existing_names)))
results = [["Structure", "Mode", "Operation", "Time(sec)"]]
for mode_name, records in [("random", records_shuffled), ("sorted", records_sorted)]:
for structure_name, init_func, insert_func, find_func, delete_func, list_func in [
("LinkedList", None, ll_insert, ll_find, ll_delete, ll_list_all),
("BST", None, bst_insert, bst_find, bst_delete, bst_list_all),
("HashTable", ht_create, ht_insert, ht_find, ht_delete, ht_list_all)
]:
ins, fin, dlt, _ = run_experiment(structure_name, init_func, insert_func, find_func, delete_func, list_func,
records, query_names, delete_names)
results.append([structure_name, mode_name, "insert", ins])
results.append([structure_name, mode_name, "search_110", fin])
results.append([structure_name, mode_name, "delete_50", dlt])
with open(csv_path, "w", newline="", encoding='utf-8') as f:
writer = csv.writer(f)
writer.writerows(results)
print(f"Results saved to {csv_path}")
structures = ["LinkedList", "HashTable", "BST"]
random_insert = []
random_search = []
random_delete = []
sorted_insert = []
sorted_search = []
sorted_delete = []
for row in results[1:]:
structure, mode, operation, time_val = row
if mode == "random" and operation == "insert":
random_insert.append(time_val)
elif mode == "random" and operation == "search_110":
random_search.append(time_val)
elif mode == "random" and operation == "delete_50":
random_delete.append(time_val)
elif mode == "sorted" and operation == "insert":
sorted_insert.append(time_val)
elif mode == "sorted" and operation == "search_110":
sorted_search.append(time_val)
elif mode == "sorted" and operation == "delete_50":
sorted_delete.append(time_val)
# Построение и сохранение графика
fig, axes = plt.subplots(1, 3, figsize=(18, 6))
x = np.arange(len(structures))
width = 0.35
axes[0].bar(x - width / 2, random_insert, width, label="Random", color="steelblue")
axes[0].bar(x + width / 2, sorted_insert, width, label="Sorted", color="coral")
axes[0].set_xticks(x)
axes[0].set_xticklabels(structures)
axes[0].set_ylabel("Time (sec)")
axes[0].set_title("Insert")
axes[0].legend()
axes[0].grid(True)
axes[1].bar(x - width / 2, random_search, width, label="Random", color="steelblue")
axes[1].bar(x + width / 2, sorted_search, width, label="Sorted", color="coral")
axes[1].set_xticks(x)
axes[1].set_xticklabels(structures)
axes[1].set_ylabel("Time (sec)")
axes[1].set_title("Search")
axes[1].legend()
axes[1].grid(True)
axes[2].bar(x - width / 2, random_delete, width, label="Random", color="steelblue")
axes[2].bar(x + width / 2, sorted_delete, width, label="Sorted", color="coral")
axes[2].set_xticks(x)
axes[2].set_xticklabels(structures)
axes[2].set_ylabel("Time (sec)")
axes[2].set_title("Delete")
axes[2].legend()
axes[2].grid(True)
plt.tight_layout()
plt.savefig(graph_path, dpi=300)
print(f"Graph saved to {graph_path}")
plt.show()
if __name__ == "__main__":
main()