Merge pull request '[1] Первая лабораторная работа' (#235) from mylnikovas/2026-rff_mp:task_1 into develop

Reviewed-on: UNN/2026-rff_mp#235
This commit is contained in:
VladimirGub 2026-05-30 11:40:29 +00:00
commit 6bf6bc0c5f
5 changed files with 354 additions and 0 deletions

View File

@ -0,0 +1,92 @@
def main():
N = 10000
random.seed(42)
records_sorted = [(f"User_{i:05d}", f"8-999-123-{i:04d}") for i in range(N)]
records_shuffled = records_sorted.copy()
random.shuffle(records_shuffled)
search_existing = [random.choice(records_sorted)[0] for _ in range(100)]
search_non_existing = [f"None_{i}" for i in range(10)]
search_names = search_existing + search_non_existing
delete_names = [random.choice(records_sorted)[0] for _ in range(50)]
csv_rows = [["Structure", "Mode", "Operation", "Time (sec)"]]
plot_data = []
def run_experiment(struct_type, mode, dataset):
print(f"Start: {struct_type} | Mode: {mode}...")
times_insert, times_find, times_delete = [], [], []
for round_idx in range(1, 6):
if struct_type == "LinkedList": container = None
elif struct_type == "HashTable": container = ht_create(size=1000)
elif struct_type == "BST": container = None
# А. Вставка
start = time.perf_counter()
if struct_type == "LinkedList":
for name, phone in dataset: container = ll_insert(container, name, phone)
elif struct_type == "HashTable":
for name, phone in dataset: ht_insert(container, name, phone)
elif struct_type == "BST":
for name, phone in dataset: container = bst_insert(container, name, phone)
t_ins = time.perf_counter() - start
times_insert.append(t_ins)
csv_rows.append([struct_type, mode, f"insert (number {round_idx})", f"{t_ins:.6f}"])
# Б. Поиск
start = time.perf_counter()
if struct_type == "LinkedList":
for name in search_names: ll_find(container, name)
elif struct_type == "HashTable":
for name in search_names: ht_find(container, name)
elif struct_type == "BST":
for name in search_names: bst_find(container, name)
t_find = time.perf_counter() - start
times_find.append(t_find)
csv_rows.append([struct_type, mode, f"find (number {round_idx})", f"{t_find:.6f}"])
# В. Удаление
start = time.perf_counter()
if struct_type == "LinkedList":
for name in delete_names: container = ll_delete(container, name)
elif struct_type == "HashTable":
for name in delete_names: ht_delete(container, name)
elif struct_type == "BST":
for name in delete_names: container = bst_delete(container, name)
t_del = time.perf_counter() - start
times_delete.append(t_del)
csv_rows.append([struct_type, mode, f"delete (number {round_idx})", f"{t_del:.6f}"])
# Запись средних значений
csv_rows.append([struct_type, mode, "Insert (average)", f"{sum(times_insert)/5:.6f}"])
csv_rows.append([struct_type, mode, "Find (average)", f"{sum(times_find)/5:.6f}"])
csv_rows.append([struct_type, mode, "Delete (average)", f"{sum(times_delete)/5:.6f}"])
avg_ins = sum(times_insert) / 5
avg_find = sum(times_find) / 5
avg_del = sum(times_delete) / 5
plot_data.append((struct_type, mode, avg_ins, avg_find, avg_del))
# Запуск всех тестов
run_experiment("LinkedList", "random", records_shuffled)
run_experiment("LinkedList", "sorted", records_sorted)
run_experiment("HashTable", "random", records_shuffled)
run_experiment("HashTable", "sorted", records_sorted)
run_experiment("BST", "random", records_shuffled)
run_experiment("BST", "sorted", records_sorted)
# Сохранение в CSV
with open("results.csv", "w", newline="", encoding="utf-8") as f:
writer = csv.writer(f)
writer.writerows(csv_rows)
print("\n[Успех] Все тесты завершены! Результаты сохранены в 'results.csv'.")
generate_performance_charts(plot_data)
if __name__ == '__main__':
experiment_thread = threading.Thread(target=main)
experiment_thread.start()
experiment_thread.join()

View File

@ -0,0 +1,153 @@
import csv
import random
import sys
import time
import threading
sys.setrecursionlimit(30000)
threading.stack_size(64*1024*1024)
def ll_insert(head, name, phone):
"""Добавляет запись или обновляет телефон, если имя уже существует. Возвращает новую голову списка."""
curr = head
while curr is not None:
if curr["name"] == name:
curr["phone"] = phone
return head
curr = curr["next"]
new_node = {"name": name, "phone": phone, "next": head}
return new_node
def ll_find(head, name):
"""Ищет узел по имени. Возвращает телефон или None."""
curr = head
while curr is not None:
if curr["name"] == name:
return curr["phone"]
curr = curr["next"]
return None
def ll_delete(head, name):
"""Удаляет узел по имени. Возвращает новую голову списка."""
curr = head
prev = None
while curr is not None:
if curr["name"] == name:
if prev is None:
return curr["next"]
else:
prev["next"] = curr["next"]
return head
prev = curr
curr = curr["next"]
return head
def ll_list_all(head):
"""Собирает все записи в список и сортирует их по имени."""
records = []
curr = head
while curr is not None:
records.append((curr["name"], curr["phone"]))
curr = curr["next"]
records.sort(key=lambda x: x[0])
return records
def ht_create(size=1000):
"""Создает пустую хеш-таблицу заданного размера."""
return [None] * size
def ht_insert(buckets, name, phone):
"""Вычисляет индекс бакета и вызывает ll_insert."""
idx = abs(hash(name)) % len(buckets)
buckets[idx] = ll_insert(buckets[idx], name, phone)
def ht_find(buckets, name):
"""Вычисляет индекс бакета и вызывает ll_find."""
idx = abs(hash(name)) % len(buckets)
return ll_find(buckets[idx], name)
def ht_delete(buckets, name):
"""Вычисляет индекс бакета и вызывает ll_delete."""
idx = abs(hash(name)) % len(buckets)
buckets[idx] = ll_delete(buckets[idx], name)
def ht_list_all(buckets):
"""Собирает записи из всех бакетов и сортирует их по имени."""
records = []
for head in buckets:
curr = head
while curr is not None:
records.append((curr["name"], curr["phone"]))
curr = curr["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["phone"] = phone
elif name < root["name"]:
root["left"] = bst_insert(root["left"], name, phone)
else:
root["right"] = bst_insert(root["right"], name, 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_delete(root, name):
"""Рекурсивное удаление узла из BST."""
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"] is not None:
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):
"""Центрированный обход дерева для сбора записей."""
records = []
def _inorder(node):
if node is not None:
_inorder(node["left"])
records.append((node["name"], node["phone"]))
_inorder(node["right"])
_inorder(root)
return records

Binary file not shown.

View File

@ -0,0 +1,109 @@
Structure,Mode,Operation,Time (sec)
LinkedList,random,insert (number 1),4.815837
LinkedList,random,find (number 1),0.052892
LinkedList,random,delete (number 1),0.027702
LinkedList,random,insert (number 2),4.566321
LinkedList,random,find (number 2),0.049406
LinkedList,random,delete (number 2),0.024055
LinkedList,random,insert (number 3),4.912175
LinkedList,random,find (number 3),0.048987
LinkedList,random,delete (number 3),0.025564
LinkedList,random,insert (number 4),5.096061
LinkedList,random,find (number 4),0.059990
LinkedList,random,delete (number 4),0.026717
LinkedList,random,insert (number 5),5.182869
LinkedList,random,find (number 5),0.055768
LinkedList,random,delete (number 5),0.027361
LinkedList,random,Insert (average),4.914653
LinkedList,random,Find (average),0.053409
LinkedList,random,Delete (average),0.026280
LinkedList,sorted,insert (number 1),4.635120
LinkedList,sorted,find (number 1),0.057343
LinkedList,sorted,delete (number 1),0.028141
LinkedList,sorted,insert (number 2),4.673462
LinkedList,sorted,find (number 2),0.058540
LinkedList,sorted,delete (number 2),0.030570
LinkedList,sorted,insert (number 3),4.720830
LinkedList,sorted,find (number 3),0.050661
LinkedList,sorted,delete (number 3),0.026368
LinkedList,sorted,insert (number 4),4.413700
LinkedList,sorted,find (number 4),0.061699
LinkedList,sorted,delete (number 4),0.040006
LinkedList,sorted,insert (number 5),4.487595
LinkedList,sorted,find (number 5),0.054366
LinkedList,sorted,delete (number 5),0.031918
LinkedList,sorted,Insert (average),4.586142
LinkedList,sorted,Find (average),0.056522
LinkedList,sorted,Delete (average),0.031401
HashTable,random,insert (number 1),0.013673
HashTable,random,find (number 1),0.000142
HashTable,random,delete (number 1),0.000081
HashTable,random,insert (number 2),0.012924
HashTable,random,find (number 2),0.000111
HashTable,random,delete (number 2),0.000056
HashTable,random,insert (number 3),0.013575
HashTable,random,find (number 3),0.000178
HashTable,random,delete (number 3),0.000090
HashTable,random,insert (number 4),0.012327
HashTable,random,find (number 4),0.000112
HashTable,random,delete (number 4),0.000058
HashTable,random,insert (number 5),0.012698
HashTable,random,find (number 5),0.000151
HashTable,random,delete (number 5),0.000055
HashTable,random,Insert (average),0.013039
HashTable,random,Find (average),0.000139
HashTable,random,Delete (average),0.000068
HashTable,sorted,insert (number 1),0.012770
HashTable,sorted,find (number 1),0.000128
HashTable,sorted,delete (number 1),0.000067
HashTable,sorted,insert (number 2),0.030806
HashTable,sorted,find (number 2),0.000143
HashTable,sorted,delete (number 2),0.000074
HashTable,sorted,insert (number 3),0.011925
HashTable,sorted,find (number 3),0.000142
HashTable,sorted,delete (number 3),0.000072
HashTable,sorted,insert (number 4),0.012686
HashTable,sorted,find (number 4),0.000263
HashTable,sorted,delete (number 4),0.000114
HashTable,sorted,insert (number 5),0.011504
HashTable,sorted,find (number 5),0.000139
HashTable,sorted,delete (number 5),0.000075
HashTable,sorted,Insert (average),0.015938
HashTable,sorted,Find (average),0.000163
HashTable,sorted,Delete (average),0.000080
BST,random,insert (number 1),0.042690
BST,random,find (number 1),0.000424
BST,random,delete (number 1),0.000232
BST,random,insert (number 2),0.042969
BST,random,find (number 2),0.000436
BST,random,delete (number 2),0.000248
BST,random,insert (number 3),0.041771
BST,random,find (number 3),0.000462
BST,random,delete (number 3),0.000280
BST,random,insert (number 4),0.046081
BST,random,find (number 4),0.000392
BST,random,delete (number 4),0.000199
BST,random,insert (number 5),0.042080
BST,random,find (number 5),0.000404
BST,random,delete (number 5),0.000213
BST,random,Insert (average),0.043118
BST,random,Find (average),0.000424
BST,random,Delete (average),0.000234
BST,sorted,insert (number 1),21.678231
BST,sorted,find (number 1),0.198191
BST,sorted,delete (number 1),0.080743
BST,sorted,insert (number 2),25.945965
BST,sorted,find (number 2),0.197616
BST,sorted,delete (number 2),0.095071
BST,sorted,insert (number 3),25.663677
BST,sorted,find (number 3),0.194259
BST,sorted,delete (number 3),0.081219
BST,sorted,insert (number 4),22.098788
BST,sorted,find (number 4),0.197365
BST,sorted,delete (number 4),0.090777
BST,sorted,insert (number 5),22.467530
BST,sorted,find (number 5),0.168119
BST,sorted,delete (number 5),0.071693
BST,sorted,Insert (average),23.570838
BST,sorted,Find (average),0.191110
BST,sorted,Delete (average),0.083900
Internal Server Error - DRE.lab repo

Internal Server Error

Gitea Version: 1.22.0