[1]lab1 #208

Merged
AndreyUrs merged 4 commits from smirnovad/2026-rff_mp:lab11 into develop 2026-05-30 11:44:53 +00:00
4 changed files with 269 additions and 0 deletions

View File

@ -0,0 +1,17 @@
# Лабораторная работа №1: Структуры данных
Выполнен замер производительности на выборке N=10000.
## Сводная таблица (Средние значения)
| Тип | Режим | Вставка | Поиск | Удаление |
| :--- | :--- | :--- | :--- | :--- |
| LinkedList | random | 0.00171 | 0.03253 | 0.01889 |
| HashTable | random | 0.00315 | 0.00008 | 0.00005 |
| BST | random | 0.02405 | 0.00021 | 0.00011 |
| LinkedList | sorted | 0.00139 | 0.03529 | 0.01801 |
| HashTable | sorted | 0.00289 | 0.00008 | 0.00004 |
| BST | sorted | 10.51532 | 0.08273 | 0.05241 |
## Основные выводы
1. **BST** крайне чувствителен к порядку: на отсортированных данных скорость падает из-за превращения дерева в список.
2. **HashTable** — самая стабильная структура, время операций почти не зависит от входной последовательности.
3. **LinkedList** показывает худшее время на операциях поиска из-за необходимости полного перебора.

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

View File

@ -0,0 +1,221 @@
import time
import random
import csv
from pathlib import Path
import matplotlib.pyplot as plt
import sys
# Увеличиваем лимит рекурсии для работы с глубокими деревьями (особенно на сортированных данных)
sys.setrecursionlimit(15000)
# Настройка путей (используем pathlib для гибкости)
ROOT_DIR = Path(r"C:\Users\andre\2026-rff_mp\smirnovad\lab1")
DOCS_DIR = ROOT_DIR / "docs"
DATA_DIR = DOCS_DIR / "data"
# Создание необходимых директорий
DATA_DIR.mkdir(parents=True, exist_ok=True)
# --- 1. СВЯЗНЫЙ СПИСОК (LinkedList) ---
def ll_insert(first_node, name, phone):
"""Добавление в начало списка (O(1))"""
return {'name': name, 'phone': phone, 'next': first_node}
def ll_find(first_node, name):
"""Линейный поиск по имени"""
item = first_node
while item:
if item['name'] == name:
return item['phone']
item = item['next']
return None
def ll_delete(first_node, name):
"""Удаление узла по имени"""
if not first_node:
return None
if first_node['name'] == name:
return first_node['next']
prev = first_node
while prev['next']:
if prev['next']['name'] == name:
prev['next'] = prev['next']['next']
return first_node
prev = prev['next']
return first_node
def ll_list_all(first_node):
"""Вывод всех записей в алфавитном порядке"""
result_list = []
item = first_node
while item:
result_list.append((item['name'], item['phone']))
item = item['next']
return sorted(result_list)
# --- 2. ХЕШ-ТАБЛИЦА (Hash Table) ---
def ht_insert(hash_table, name, phone):
slot = hash(name) % len(hash_table)
hash_table[slot] = ll_insert(hash_table[slot], name, phone)
def ht_find(hash_table, name):
slot = hash(name) % len(hash_table)
return ll_find(hash_table[slot], name)
def ht_delete(hash_table, name):
slot = hash(name) % len(hash_table)
hash_table[slot] = ll_delete(hash_table[slot], name)
def ht_list_all(hash_table):
"""Сбор данных из всех бакетов"""
total_data = []
for bucket in hash_table:
node = bucket
while node:
total_data.append((node['name'], node['phone']))
node = node['next']
return sorted(total_data)
# --- 3. ДВОИЧНОЕ ДЕРЕВО ПОИСКА (BST) ---
def bst_insert(root, name, phone):
if not root:
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 not root:
return None
if root['name'] == name:
return root['phone']
if name < root['name']:
return bst_find(root['left'], name)
return bst_find(root['right'], name)
def bst_delete(root, name):
"""Удаление узла в BST"""
if not root:
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 not root['left']: return root['right']
if not root['right']: return root['left']
# Поиск минимального в правом поддереве
min_node = root['right']
while min_node['left']:
min_node = min_node['left']
root['name'], root['phone'] = min_node['name'], min_node['phone']
root['right'] = bst_delete(root['right'], min_node['name'])
return root
# --- ЭКСПЕРИМЕНТАЛЬНАЯ ЧАСТЬ ---
log_entries = []
stats_summary = []
def run_test(structure_name, data_mode, dataset):
print(f"Тестирование: {structure_name} | Режим: {data_mode}")
t_ins, t_find, t_del = [], [], []
for run_idx in range(5): # 5 итераций
# Инициализация хранилища
storage = [None] * 1024 if structure_name == "HashTable" else None
# 1. Замер вставки
start = time.perf_counter()
for n, p in dataset:
if structure_name == "LinkedList": storage = ll_insert(storage, n, p)
elif structure_name == "HashTable": ht_insert(storage, n, p)
elif structure_name == "BST": storage = bst_insert(storage, n, p)
t_ins.append(time.perf_counter() - start)
# 2. Замер поиска (100 существующих + 10 отсутствующих)
test_names = [x[0] for x in random.sample(dataset, 100)] + [f"Missing_{j}" for j in range(10)]
start = time.perf_counter()
for name_to_find in test_names:
if structure_name == "LinkedList": ll_find(storage, name_to_find)
elif structure_name == "HashTable": ht_find(storage, name_to_find)
elif structure_name == "BST": bst_find(storage, name_to_find)
t_find.append(time.perf_counter() - start)
# 3. Замер удаления (50 записей)
test_dels = [x[0] for x in random.sample(dataset, 50)]
start = time.perf_counter()
for name_to_del in test_dels:
if structure_name == "LinkedList": storage = ll_delete(storage, name_to_del)
elif structure_name == "HashTable": ht_delete(storage, name_to_del)
elif structure_name == "BST": bst_delete(storage, name_to_del)
t_del.append(time.perf_counter() - start)
log_entries.append([structure_name, data_mode, f"Run_{run_idx+1}", t_ins[-1], t_find[-1], t_del[-1]])
# Считаем среднее
avg_i, avg_f, avg_d = sum(t_ins)/5, sum(t_find)/5, sum(t_del)/5
stats_summary.append({"type": structure_name, "mode": data_mode, "ins": avg_i, "find": avg_f, "del": avg_d})
# Генерация данных
N_COUNT = 10000
raw_data = [(f"User_{i:05d}", f"{random.randint(100, 999)}-{random.randint(10, 99)}") for i in range(N_COUNT)]
data_shuffled = random.sample(raw_data, len(raw_data))
data_sorted = sorted(raw_data)
# Запуск тестов
for mode_label, data_src in [("random", data_shuffled), ("sorted", data_sorted)]:
for s_kind in ["LinkedList", "HashTable", "BST"]:
run_test(s_kind, mode_label, data_src)
# Сохранение CSV
with open(DATA_DIR / "performance_stats.csv", "w", newline="", encoding="utf-8") as f:
writer = csv.writer(f)
writer.writerow(["Structure", "Input_Mode", "Iteration", "Insert_Sec", "Find_Sec", "Delete_Sec"])
writer.writerows(log_entries)
# Построение графиков
def generate_visuals():
ops = ["Вставка", "Поиск", "Удаление"]
structs = ["LinkedList", "HashTable", "BST"]
palette = ["#3498db", "#9b59b6", "#2ecc71"] # Другие цвета
# График влияния порядка
fig, axes = plt.subplots(1, 3, figsize=(16, 5))
fig.suptitle("Анализ влияния упорядоченности данных", fontsize=14)
for idx, s_name in enumerate(structs):
r_vals = next(s for s in stats_summary if s['type'] == s_name and s['mode'] == "random")
s_vals = next(s for s in stats_summary if s['type'] == s_name and s['mode'] == "sorted")
pos = [0, 1, 2]
axes[idx].bar([p - 0.2 for p in pos], [r_vals['ins'], r_vals['find'], r_vals['del']], 0.4, label='Random', color=palette[0])
axes[idx].bar([p + 0.2 for p in pos], [s_vals['ins'], s_vals['find'], s_vals['del']], 0.4, label='Sorted', color="#e74c3c")
axes[idx].set_title(s_name)
axes[idx].set_xticks(pos)
axes[idx].set_xticklabels(ops)
axes[idx].legend()
plt.tight_layout()
plt.savefig(DATA_DIR / "impact_analysis.png")
generate_visuals()
# Генерация отчета
with open(DOCS_DIR / "LAB_REPORT.md", "w", encoding="utf-8") as f:
f.write("# Лабораторная работа №1: Структуры данных\n\n")
f.write(f"Выполнен замер производительности на выборке N={N_COUNT}.\n")
f.write("## Сводная таблица (Средние значения)\n")
f.write("| Тип | Режим | Вставка | Поиск | Удаление |\n| :--- | :--- | :--- | :--- | :--- |\n")
for s in stats_summary:
f.write(f"| {s['type']} | {s['mode']} | {s['ins']:.5f} | {s['find']:.5f} | {s['del']:.5f} |\n")
f.write("\n## Основные выводы\n")
f.write("1. **BST** крайне чувствителен к порядку: на отсортированных данных скорость падает из-за превращения дерева в список.\n")
f.write("2. **HashTable** — самая стабильная структура, время операций почти не зависит от входной последовательности.\n")
f.write("3. **LinkedList** показывает худшее время на операциях поиска из-за необходимости полного перебора.")
print(f"Все файлы успешно сохранены в {DOCS_DIR}")

View File

@ -0,0 +1,31 @@
Structure,Input_Mode,Iteration,Insert_Sec,Find_Sec,Delete_Sec
LinkedList,random,Run_1,0.0023578000254929066,0.031007900135591626,0.01914949994534254
LinkedList,random,Run_2,0.0014043999835848808,0.035298199858516455,0.02021360001526773
LinkedList,random,Run_3,0.0016908999532461166,0.031882400158792734,0.016559200128540397
LinkedList,random,Run_4,0.0016268000472337008,0.033718999940901995,0.01765769999474287
LinkedList,random,Run_5,0.00146949989721179,0.030750300036743283,0.020888000028207898
HashTable,random,Run_1,0.003547400003299117,7.690000347793102e-05,6.220000796020031e-05
HashTable,random,Run_2,0.0028089999686926603,6.849993951618671e-05,3.900006413459778e-05
HashTable,random,Run_3,0.002920700004324317,7.139984518289566e-05,4.020007327198982e-05
HashTable,random,Run_4,0.003132300218567252,6.630015559494495e-05,3.860006108880043e-05
HashTable,random,Run_5,0.003326199948787689,0.00011060014367103577,6.16998877376318e-05
BST,random,Run_1,0.021002399967983365,0.00020360015332698822,0.00011419993825256824
BST,random,Run_2,0.020290900021791458,0.00019980012439191341,0.00010569998994469643
BST,random,Run_3,0.019706800114363432,0.00019660010002553463,0.00010689999908208847
BST,random,Run_4,0.019484999822452664,0.00018949992954730988,0.0001066999975591898
BST,random,Run_5,0.03975450014695525,0.00024339999072253704,0.00013699987903237343
LinkedList,sorted,Run_1,0.0015730001032352448,0.03809090005233884,0.01893949997611344
LinkedList,sorted,Run_2,0.001297699986025691,0.033360299887135625,0.01909619988873601
LinkedList,sorted,Run_3,0.0015416000969707966,0.03634240012615919,0.016841999953612685
LinkedList,sorted,Run_4,0.0012899001594632864,0.03580150008201599,0.0170306998770684
LinkedList,sorted,Run_5,0.0012546998914331198,0.03284729993902147,0.018117799889296293
HashTable,sorted,Run_1,0.0034030000679194927,8.430005982518196e-05,3.66999302059412e-05
HashTable,sorted,Run_2,0.002653100062161684,6.769993342459202e-05,3.760005347430706e-05
HashTable,sorted,Run_3,0.0026434999890625477,6.690016016364098e-05,3.8400059565901756e-05
HashTable,sorted,Run_4,0.002997299889102578,7.299985736608505e-05,4.179985262453556e-05
HashTable,sorted,Run_5,0.002777900081127882,8.819997310638428e-05,3.800005652010441e-05
BST,sorted,Run_1,9.951400500023738,0.07922379998490214,0.0600940000731498
BST,sorted,Run_2,10.377625699853525,0.08713930007070303,0.05045670014806092
BST,sorted,Run_3,12.112230099970475,0.08630810002796352,0.050702399807050824
BST,sorted,Run_4,10.117846999783069,0.0832209000363946,0.05910569988191128
BST,sorted,Run_5,10.017497000051662,0.07774659991264343,0.041689899982884526
1 Structure Input_Mode Iteration Insert_Sec Find_Sec Delete_Sec
2 LinkedList random Run_1 0.0023578000254929066 0.031007900135591626 0.01914949994534254
3 LinkedList random Run_2 0.0014043999835848808 0.035298199858516455 0.02021360001526773
4 LinkedList random Run_3 0.0016908999532461166 0.031882400158792734 0.016559200128540397
5 LinkedList random Run_4 0.0016268000472337008 0.033718999940901995 0.01765769999474287
6 LinkedList random Run_5 0.00146949989721179 0.030750300036743283 0.020888000028207898
7 HashTable random Run_1 0.003547400003299117 7.690000347793102e-05 6.220000796020031e-05
8 HashTable random Run_2 0.0028089999686926603 6.849993951618671e-05 3.900006413459778e-05
9 HashTable random Run_3 0.002920700004324317 7.139984518289566e-05 4.020007327198982e-05
10 HashTable random Run_4 0.003132300218567252 6.630015559494495e-05 3.860006108880043e-05
11 HashTable random Run_5 0.003326199948787689 0.00011060014367103577 6.16998877376318e-05
12 BST random Run_1 0.021002399967983365 0.00020360015332698822 0.00011419993825256824
13 BST random Run_2 0.020290900021791458 0.00019980012439191341 0.00010569998994469643
14 BST random Run_3 0.019706800114363432 0.00019660010002553463 0.00010689999908208847
15 BST random Run_4 0.019484999822452664 0.00018949992954730988 0.0001066999975591898
16 BST random Run_5 0.03975450014695525 0.00024339999072253704 0.00013699987903237343
17 LinkedList sorted Run_1 0.0015730001032352448 0.03809090005233884 0.01893949997611344
18 LinkedList sorted Run_2 0.001297699986025691 0.033360299887135625 0.01909619988873601
19 LinkedList sorted Run_3 0.0015416000969707966 0.03634240012615919 0.016841999953612685
20 LinkedList sorted Run_4 0.0012899001594632864 0.03580150008201599 0.0170306998770684
21 LinkedList sorted Run_5 0.0012546998914331198 0.03284729993902147 0.018117799889296293
22 HashTable sorted Run_1 0.0034030000679194927 8.430005982518196e-05 3.66999302059412e-05
23 HashTable sorted Run_2 0.002653100062161684 6.769993342459202e-05 3.760005347430706e-05
24 HashTable sorted Run_3 0.0026434999890625477 6.690016016364098e-05 3.8400059565901756e-05
25 HashTable sorted Run_4 0.002997299889102578 7.299985736608505e-05 4.179985262453556e-05
26 HashTable sorted Run_5 0.002777900081127882 8.819997310638428e-05 3.800005652010441e-05
27 BST sorted Run_1 9.951400500023738 0.07922379998490214 0.0600940000731498
28 BST sorted Run_2 10.377625699853525 0.08713930007070303 0.05045670014806092
29 BST sorted Run_3 12.112230099970475 0.08630810002796352 0.050702399807050824
30 BST sorted Run_4 10.117846999783069 0.0832209000363946 0.05910569988191128
31 BST sorted Run_5 10.017497000051662 0.07774659991264343 0.041689899982884526