[1] zadanie1

This commit is contained in:
smirnovad 2026-05-14 22:40:34 +03:00
parent 2e92918882
commit dde8ede88d
6 changed files with 313 additions and 0 deletions

View File

@ -0,0 +1,249 @@
import time
import random
import csv
import os
import sys
import matplotlib.pyplot as plt
sys.setrecursionlimit(20000)
BASE_PATH = r"C:\Users\andre\2026-rff_mp\smirnovad\lab1"
DOCS_PATH = os.path.join(BASE_PATH, "docs")
DATA_PATH = os.path.join(DOCS_PATH, "data")
for p in [DOCS_PATH, DATA_PATH]:
if not os.path.exists(p):
os.makedirs(p)
def ll_insert(head, name, phone):
return {'name': name, 'phone': phone, 'next': 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 not head: 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):
res = []
curr = head
while curr:
res.append((curr['name'], curr['phone']))
curr = curr['next']
return sorted(res)
def ht_insert(buckets, name, phone):
idx = hash(name) % len(buckets)
buckets[idx] = ll_insert(buckets[idx], name, phone)
def ht_find(buckets, name):
idx = hash(name) % len(buckets)
return ll_find(buckets[idx], name)
def ht_delete(buckets, name):
idx = hash(name) % len(buckets)
buckets[idx] = ll_delete(buckets[idx], name)
def ht_list_all(buckets):
all_recs = []
for b in buckets:
curr = b
while curr:
all_recs.append((curr['name'], curr['phone']))
curr = curr['next']
return sorted(all_recs)
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):
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']
temp = root['right']
while temp['left']: temp = temp['left']
root['name'], root['phone'] = temp['name'], temp['phone']
root['right'] = bst_delete(root['right'], temp['name'])
return root
def bst_list_all(root):
res = []
def _inorder(node):
if node:
_inorder(node['left'])
res.append((node['name'], node['phone']))
_inorder(node['right'])
_inorder(root)
return res
all_results_csv = []
summary_for_report = []
def run_experiment(struct_type, mode, data):
print(f"Processing: {struct_type} ({mode})")
ins_times, find_times, del_times = [], [], []
for i in range(5):
container = [None]*1000 if struct_type == "HashTable" else None
start = time.perf_counter()
for n, p in data:
if struct_type == "LinkedList": container = ll_insert(container, n, p)
elif struct_type == "HashTable": ht_insert(container, n, p)
elif struct_type == "BST": container = bst_insert(container, n, p)
ins_times.append(time.perf_counter() - start)
search_list = [d[0] for d in random.sample(data, 100)] + [f"None_{j}" for j in range(10)]
start = time.perf_counter()
for s_name in search_list:
if struct_type == "LinkedList": ll_find(container, s_name)
elif struct_type == "HashTable": ht_find(container, s_name)
elif struct_type == "BST": bst_find(container, s_name)
find_times.append(time.perf_counter() - start)
del_list = [d[0] for d in random.sample(data, 50)]
start = time.perf_counter()
for d_name in del_list:
if struct_type == "LinkedList": container = ll_delete(container, d_name)
elif struct_type == "HashTable": ht_delete(container, d_name)
elif struct_type == "BST": container = bst_delete(container, d_name)
del_times.append(time.perf_counter() - start)
all_results_csv.append([struct_type, mode, f"Run {i+1}", ins_times[-1], find_times[-1], del_times[-1]])
avg_ins = sum(ins_times) / 5
avg_find = sum(find_times) / 5
avg_del = sum(del_times) / 5
all_results_csv.append([struct_type, mode, "AVERAGE", avg_ins, avg_find, avg_del])
summary_for_report.append({"name": struct_type, "mode": mode, "ins": avg_ins, "find": avg_find, "del": avg_del})
N = 10000
records_raw = [(f"User_{i:05d}", f"8-900-{random.randint(100, 999)}") for i in range(N)]
records_shuffled = records_raw[:]
random.shuffle(records_shuffled)
records_sorted = sorted(records_raw)
for m_name, d_set in [("случайный", records_shuffled), ("сортированный", records_sorted)]:
for s_type in ["LinkedList", "HashTable", "BST"]:
run_experiment(s_type, m_name, d_set)
with open(os.path.join(DATA_PATH, "results.csv"), "w", newline="", encoding="utf-8") as f:
writer = csv.writer(f)
writer.writerow(["Структура", "Режим", "Итерация", "Вставка", "Поиск", "Удаление"])
writer.writerows(all_results_csv)
def create_plots():
labels = ["insert", "find", "delete"]
structs = ["LinkedList", "HashTable", "BST"]
colors = ['#5dade2', '#e67e22', '#58d68d']
fig1, axs = plt.subplots(1, 3, figsize=(18, 6))
fig1.suptitle("Влияние порядка данных на время операций", fontsize=16, fontweight='bold')
for i, s_name in enumerate(structs):
rand_data = next(r for r in summary_for_report if r['name'] == s_name and r['mode'] == "случайный")
sort_data = next(r for r in summary_for_report if r['name'] == s_name and r['mode'] == "сортированный")
x = [0, 1, 2]
width = 0.35
axs[i].bar([p - width/2 for p in x], [rand_data['ins'], rand_data['find'], rand_data['del']], width, label='случайный', color=colors[0])
axs[i].bar([p + width/2 for p in x], [sort_data['ins'], sort_data['find'], sort_data['del']], width, label='сортированный', color='#e74c3c', alpha=0.8)
axs[i].set_title(s_name, fontweight='bold')
axs[i].set_xticks(x)
axs[i].set_xticklabels(labels)
axs[i].set_ylabel("Время (с)")
axs[i].legend()
axs[i].grid(axis='y', linestyle='--', alpha=0.3)
plt.tight_layout(rect=[0, 0.03, 1, 0.95])
plt.savefig(os.path.join(DATA_PATH, "order_impact.png"))
fig2, axs2 = plt.subplots(1, 3, figsize=(18, 6))
fig2.suptitle(f"Сравнение структур данных (N={N})", fontsize=16, fontweight='bold')
op_keys = ['ins', 'find', 'del']
op_names = ['insert', 'find', 'delete']
for i, op in enumerate(op_keys):
plot_labels = []
plot_values = []
plot_colors = []
for r in summary_for_report:
plot_labels.append(f"{r['name']}\n({r['mode'][:4]})")
plot_values.append(r[op])
if r['name'] == "LinkedList": plot_colors.append(colors[0])
elif r['name'] == "HashTable": plot_colors.append(colors[1])
else: plot_colors.append(colors[2])
bars = axs2[i].bar(plot_labels, plot_values, color=plot_colors)
axs2[i].set_title(f"Операция: {op_names[i]}", fontweight='bold')
axs2[i].set_ylabel("Время (с)")
axs2[i].tick_params(axis='x', rotation=15)
for bar in bars:
height = bar.get_height()
axs2[i].text(bar.get_x() + bar.get_width()/2., height, f'{height:.4f}', ha='center', va='bottom', fontsize=8)
plt.tight_layout(rect=[0, 0.03, 1, 0.95])
plt.savefig(os.path.join(DATA_PATH, "struct_comparison.png"))
create_plots()
with open(os.path.join(DOCS_PATH, "report.md"), "w", encoding="utf-8") as f:
f.write("# Технический отчет: Сравнительный анализ структур данных\n\n")
f.write("## 1. Вводные данные\n")
f.write(f"Целью теста является оценка производительности LinkedList, HashTable и BST на массиве из {N} элементов. ")
f.write("Анализировались сценарии со случайным распределением и предварительной сортировкой ключей.\n\n")
f.write("## 2. Результаты измерений (AVG)\n")
f.write("| Алгоритм | Входные данные | Вставка (с) | Поиск (с) | Удаление (с) |\n")
f.write("| :--- | :--- | :--- | :--- | :--- |\n")
for r in summary_for_report:
f.write(f"| {r['name']} | {r['mode']} | {r['ins']:.6f} | {r['find']:.6f} | {r['del']:.6f} |\n")
f.write("\n## 3. Визуальный анализ\n")
f.write("### Сравнение по типам операций\n![Сравнение](data/struct_comparison.png)\n\n")
f.write("### Влияние упорядоченности на производительность\n![Влияние порядка](data/order_impact.png)\n\n")
f.write("## 4. Экспертные выводы\n")
f.write("- **Эффект вырождения BST:** На отсортированных последовательностях BST демонстрирует критический рост времени выполнения (деградация до $O(N)$). ")
f.write("Это связано с отсутствием балансировки, превращающим дерево в линейный список.\n")
f.write("- **Инвариантность HashTable:** Хеш-таблица показывает наиболее стабильные результаты. Скорость доступа не коррелирует с порядком входных данных.\n")
f.write("- **Линейная сложность LinkedList:** Связный список предсказуемо неэффективен при поиске, так как требует итерации по всей глубине структуры.\n")
f.write("- **Итоговая оценка:** Для систем с высокой интенсивностью поиска и вставки оптимальным выбором является HashTable.")
print("Готово.")

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

View File

@ -0,0 +1,37 @@
Структура,Режим,Итерация,Вставка,Поиск,Удаление
LinkedList,случайный,Run 1,0.0019714999943971634,0.029020800022408366,0.017652600072324276
LinkedList,случайный,Run 2,0.0012699998915195465,0.03224149998277426,0.019751599989831448
LinkedList,случайный,Run 3,0.0015686999540776014,0.032726099947467446,0.023450100095942616
LinkedList,случайный,Run 4,0.0012663998641073704,0.031491999980062246,0.02140070009045303
LinkedList,случайный,Run 5,0.001316299894824624,0.03115670010447502,0.01875569997355342
LinkedList,случайный,AVERAGE,0.0014785799197852612,0.03132742000743747,0.020202140044420957
HashTable,случайный,Run 1,0.0036369001027196646,7.810001261532307e-05,4.20999713242054e-05
HashTable,случайный,Run 2,0.0027166998479515314,6.680004298686981e-05,3.690016455948353e-05
HashTable,случайный,Run 3,0.002825999865308404,6.940006278455257e-05,4.0599843487143517e-05
HashTable,случайный,Run 4,0.0038201999850571156,9.25001222640276e-05,4.6800123527646065e-05
HashTable,случайный,Run 5,0.0028741999994963408,7.349997758865356e-05,4.6900007873773575e-05
HashTable,случайный,AVERAGE,0.0031747999601066113,7.606004364788533e-05,4.2660022154450415e-05
BST,случайный,Run 1,0.02340110018849373,0.000219699926674366,0.00012899981811642647
BST,случайный,Run 2,0.02266499982215464,0.000223799841478467,0.00011649983935058117
BST,случайный,Run 3,0.02390270004980266,0.0002661000471562147,0.00011879997327923775
BST,случайный,Run 4,0.02376510016620159,0.00023330003023147583,0.00013200007379055023
BST,случайный,Run 5,0.039811399998143315,0.00020990008488297462,0.00011849985457956791
BST,случайный,AVERAGE,0.02670906004495919,0.00023055998608469963,0.00012295991182327272
LinkedList,сортированный,Run 1,0.001537499949336052,0.033511900110170245,0.019870299845933914
LinkedList,сортированный,Run 2,0.001307999948039651,0.0319586000405252,0.014161000028252602
LinkedList,сортированный,Run 3,0.0014808999840170145,0.0326090999878943,0.018076500156894326
LinkedList,сортированный,Run 4,0.0013822999317198992,0.033412199933081865,0.022219100035727024
LinkedList,сортированный,Run 5,0.0012627998366951942,0.030183800030499697,0.016802300000563264
LinkedList,сортированный,AVERAGE,0.001394299929961562,0.03233512002043426,0.018225840013474225
HashTable,сортированный,Run 1,0.0034910000395029783,8.500018157064915e-05,4.449998959898949e-05
HashTable,сортированный,Run 2,0.002676100004464388,6.62999227643013e-05,3.50000336766243e-05
HashTable,сортированный,Run 3,0.0026501999236643314,6.309989839792252e-05,3.5800039768218994e-05
HashTable,сортированный,Run 4,0.003009800100699067,6.360001862049103e-05,3.800005652010441e-05
HashTable,сортированный,Run 5,0.002735199872404337,8.360017091035843e-05,3.979983739554882e-05
HashTable,сортированный,AVERAGE,0.0029124599881470204,7.232003845274449e-05,3.86199913918972e-05
BST,сортированный,Run 1,10.096050000051036,0.08805329981260002,0.06355300010181963
BST,сортированный,Run 2,10.27557749999687,0.0852949998807162,0.04538960009813309
BST,сортированный,Run 3,9.790069000096992,0.0812387999612838,0.0491947999689728
BST,сортированный,Run 4,9.99310930003412,0.08915449981577694,0.04604210006073117
BST,сортированный,Run 5,9.97979940008372,0.07943259994499385,0.049180999863892794
BST,сортированный,AVERAGE,10.026921040052548,0.08463483988307416,0.0506721000187099
1 Структура Режим Итерация Вставка Поиск Удаление
2 LinkedList случайный Run 1 0.0019714999943971634 0.029020800022408366 0.017652600072324276
3 LinkedList случайный Run 2 0.0012699998915195465 0.03224149998277426 0.019751599989831448
4 LinkedList случайный Run 3 0.0015686999540776014 0.032726099947467446 0.023450100095942616
5 LinkedList случайный Run 4 0.0012663998641073704 0.031491999980062246 0.02140070009045303
6 LinkedList случайный Run 5 0.001316299894824624 0.03115670010447502 0.01875569997355342
7 LinkedList случайный AVERAGE 0.0014785799197852612 0.03132742000743747 0.020202140044420957
8 HashTable случайный Run 1 0.0036369001027196646 7.810001261532307e-05 4.20999713242054e-05
9 HashTable случайный Run 2 0.0027166998479515314 6.680004298686981e-05 3.690016455948353e-05
10 HashTable случайный Run 3 0.002825999865308404 6.940006278455257e-05 4.0599843487143517e-05
11 HashTable случайный Run 4 0.0038201999850571156 9.25001222640276e-05 4.6800123527646065e-05
12 HashTable случайный Run 5 0.0028741999994963408 7.349997758865356e-05 4.6900007873773575e-05
13 HashTable случайный AVERAGE 0.0031747999601066113 7.606004364788533e-05 4.2660022154450415e-05
14 BST случайный Run 1 0.02340110018849373 0.000219699926674366 0.00012899981811642647
15 BST случайный Run 2 0.02266499982215464 0.000223799841478467 0.00011649983935058117
16 BST случайный Run 3 0.02390270004980266 0.0002661000471562147 0.00011879997327923775
17 BST случайный Run 4 0.02376510016620159 0.00023330003023147583 0.00013200007379055023
18 BST случайный Run 5 0.039811399998143315 0.00020990008488297462 0.00011849985457956791
19 BST случайный AVERAGE 0.02670906004495919 0.00023055998608469963 0.00012295991182327272
20 LinkedList сортированный Run 1 0.001537499949336052 0.033511900110170245 0.019870299845933914
21 LinkedList сортированный Run 2 0.001307999948039651 0.0319586000405252 0.014161000028252602
22 LinkedList сортированный Run 3 0.0014808999840170145 0.0326090999878943 0.018076500156894326
23 LinkedList сортированный Run 4 0.0013822999317198992 0.033412199933081865 0.022219100035727024
24 LinkedList сортированный Run 5 0.0012627998366951942 0.030183800030499697 0.016802300000563264
25 LinkedList сортированный AVERAGE 0.001394299929961562 0.03233512002043426 0.018225840013474225
26 HashTable сортированный Run 1 0.0034910000395029783 8.500018157064915e-05 4.449998959898949e-05
27 HashTable сортированный Run 2 0.002676100004464388 6.62999227643013e-05 3.50000336766243e-05
28 HashTable сортированный Run 3 0.0026501999236643314 6.309989839792252e-05 3.5800039768218994e-05
29 HashTable сортированный Run 4 0.003009800100699067 6.360001862049103e-05 3.800005652010441e-05
30 HashTable сортированный Run 5 0.002735199872404337 8.360017091035843e-05 3.979983739554882e-05
31 HashTable сортированный AVERAGE 0.0029124599881470204 7.232003845274449e-05 3.86199913918972e-05
32 BST сортированный Run 1 10.096050000051036 0.08805329981260002 0.06355300010181963
33 BST сортированный Run 2 10.27557749999687 0.0852949998807162 0.04538960009813309
34 BST сортированный Run 3 9.790069000096992 0.0812387999612838 0.0491947999689728
35 BST сортированный Run 4 9.99310930003412 0.08915449981577694 0.04604210006073117
36 BST сортированный Run 5 9.97979940008372 0.07943259994499385 0.049180999863892794
37 BST сортированный AVERAGE 10.026921040052548 0.08463483988307416 0.0506721000187099

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

View File

@ -0,0 +1,27 @@
# Технический отчет: Сравнительный анализ структур данных
## 1. Вводные данные
Целью теста является оценка производительности LinkedList, HashTable и BST на массиве из 10000 элементов. Анализировались сценарии со случайным распределением и предварительной сортировкой ключей.
## 2. Результаты измерений (AVG)
| Алгоритм | Входные данные | Вставка (с) | Поиск (с) | Удаление (с) |
| :--- | :--- | :--- | :--- | :--- |
| LinkedList | случайный | 0.001479 | 0.031327 | 0.020202 |
| HashTable | случайный | 0.003175 | 0.000076 | 0.000043 |
| BST | случайный | 0.026709 | 0.000231 | 0.000123 |
| LinkedList | сортированный | 0.001394 | 0.032335 | 0.018226 |
| HashTable | сортированный | 0.002912 | 0.000072 | 0.000039 |
| BST | сортированный | 10.026921 | 0.084635 | 0.050672 |
## 3. Визуальный анализ
### Сравнение по типам операций
![Сравнение](data/struct_comparison.png)
### Влияние упорядоченности на производительность
![Влияние порядка](data/order_impact.png)
## 4. Экспертные выводы
- **Эффект вырождения BST:** На отсортированных последовательностях BST демонстрирует критический рост времени выполнения (деградация до $O(N)$). Это связано с отсутствием балансировки, превращающим дерево в линейный список.
- **Инвариантность HashTable:** Хеш-таблица показывает наиболее стабильные результаты. Скорость доступа не коррелирует с порядком входных данных.
- **Линейная сложность LinkedList:** Связный список предсказуемо неэффективен при поиске, так как требует итерации по всей глубине структуры.
- **Итоговая оценка:** Для систем с высокой интенсивностью поиска и вставки оптимальным выбором является HashTable.