[1] task 1

This commit is contained in:
MariiaOs 2026-05-17 15:01:19 +03:00
parent 25341dc814
commit 634b76c127
8 changed files with 512 additions and 0 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

BIN
osipovamd/.DS_Store vendored Normal file

Binary file not shown.

BIN
osipovamd/docs/.DS_Store vendored Normal file

Binary file not shown.

BIN
osipovamd/docs/Task1.docx Normal file

Binary file not shown.

BIN
osipovamd/docs/data/.DS_Store vendored Normal file

Binary file not shown.

View File

@ -0,0 +1,19 @@
Структура,Режим,Операция,Замер1,Замер2,Замер3,Среднее
LinkedList,случайный,вставка,0.014099,0.014181,0.014180,0.014153
LinkedList,случайный,поиск,0.001849,0.001841,0.001897,0.001862
LinkedList,случайный,удаление,0.000859,0.000863,0.000825,0.000849
LinkedList,отсортированный,вставка,0.012913,0.012512,0.012566,0.012663
LinkedList,отсортированный,поиск,0.001616,0.001457,0.001696,0.001590
LinkedList,отсортированный,удаление,0.000992,0.000931,0.000940,0.000954
HashTable,случайный,вставка,0.001368,0.001415,0.001385,0.001389
HashTable,случайный,поиск,0.000162,0.000153,0.000146,0.000153
HashTable,случайный,удаление,0.000076,0.000075,0.000075,0.000075
HashTable,отсортированный,вставка,0.001275,0.001258,0.001376,0.001303
HashTable,отсортированный,поиск,0.000169,0.000139,0.000140,0.000149
HashTable,отсортированный,удаление,0.000080,0.000080,0.000079,0.000080
BST,случайный,вставка,0.000514,0.000482,0.000507,0.000501
BST,случайный,поиск,0.000081,0.000056,0.000055,0.000064
BST,случайный,удаление,0.000042,0.000038,0.000039,0.000040
BST,отсортированный,вставка,0.018947,0.018836,0.018665,0.018816
BST,отсортированный,поиск,0.002172,0.002200,0.001973,0.002115
BST,отсортированный,удаление,0.001400,0.001407,0.001390,0.001399
1 Структура Режим Операция Замер1 Замер2 Замер3 Среднее
2 LinkedList случайный вставка 0.014099 0.014181 0.014180 0.014153
3 LinkedList случайный поиск 0.001849 0.001841 0.001897 0.001862
4 LinkedList случайный удаление 0.000859 0.000863 0.000825 0.000849
5 LinkedList отсортированный вставка 0.012913 0.012512 0.012566 0.012663
6 LinkedList отсортированный поиск 0.001616 0.001457 0.001696 0.001590
7 LinkedList отсортированный удаление 0.000992 0.000931 0.000940 0.000954
8 HashTable случайный вставка 0.001368 0.001415 0.001385 0.001389
9 HashTable случайный поиск 0.000162 0.000153 0.000146 0.000153
10 HashTable случайный удаление 0.000076 0.000075 0.000075 0.000075
11 HashTable отсортированный вставка 0.001275 0.001258 0.001376 0.001303
12 HashTable отсортированный поиск 0.000169 0.000139 0.000140 0.000149
13 HashTable отсортированный удаление 0.000080 0.000080 0.000079 0.000080
14 BST случайный вставка 0.000514 0.000482 0.000507 0.000501
15 BST случайный поиск 0.000081 0.000056 0.000055 0.000064
16 BST случайный удаление 0.000042 0.000038 0.000039 0.000040
17 BST отсортированный вставка 0.018947 0.018836 0.018665 0.018816
18 BST отсортированный поиск 0.002172 0.002200 0.001973 0.002115
19 BST отсортированный удаление 0.001400 0.001407 0.001390 0.001399

493
osipovamd/docs/task1.py Normal file
View File

@ -0,0 +1,493 @@
import time
import random
import csv
import matplotlib.pyplot as plt
import numpy as np
import sys
from collections import defaultdict
# Увеличиваем лимит рекурсии для BST
sys.setrecursionlimit(10000)
def ll_insert(head, name, phone):
current = head
while current:
if current['name'] == name:
current['phone'] = phone
return head
current = current['next']
new_node = {'name': name, 'phone': phone, 'next': head}
return new_node
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 not head:
return None
if head['name'] == name:
return head['next']
current = head
while current['next']:
if current['next']['name'] == name:
current['next'] = current['next']['next']
return head
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(c) for c 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 bucket in buckets:
current = bucket
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):
"""Итеративная вставка для избежания RecursionError"""
new_node = {'name': name, 'phone': phone, 'left': None, 'right': None}
if root is None:
return new_node
current = root
while True:
if name < current['name']:
if current['left'] is None:
current['left'] = new_node
break
current = current['left']
elif name > current['name']:
if current['right'] is None:
current['right'] = new_node
break
current = current['right']
else:
current['phone'] = phone
break
return root
def bst_find(root, name):
current = root
while current:
if name == current['name']:
return current['phone']
elif name < current['name']:
current = current['left']
else:
current = current['right']
return None
def bst_find_min(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']
min_node = bst_find_min(root['right'])
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 = []
stack = []
current = root
while stack or current:
while current:
stack.append(current)
current = current['left']
current = stack.pop()
records.append((current['name'], current['phone']))
current = current['right']
return records
def copy_linked_list(head):
if not head:
return None
new_head = {'name': head['name'], 'phone': head['phone'], 'next': None}
current_new = new_head
current_old = head['next']
while current_old:
current_new['next'] = {'name': current_old['name'], 'phone': current_old['phone'], 'next': None}
current_new = current_new['next']
current_old = current_old['next']
return new_head
def copy_bst(node):
if not node:
return None
return {
'name': node['name'],
'phone': node['phone'],
'left': copy_bst(node['left']),
'right': copy_bst(node['right'])
}
def generate_test_data(N=10000):
names = [f"User_{i:05d}" for i in range(N)]
records = [(name, f"+7-999-{random.randint(1000000, 9999999)}") for name in names]
records_shuffled = records.copy()
random.shuffle(records_shuffled)
records_sorted = sorted(records, key=lambda x: x[0])
return records_shuffled, records_sorted
def get_test_queries(records, num_existing=100, num_nonexisting=10):
existing_names = [name for name, _ in random.sample(records, min(num_existing, len(records)))]
nonexisting_names = [f"None_{i:05d}" for i in range(num_nonexisting)]
queries = existing_names + nonexisting_names
random.shuffle(queries)
return queries
def get_delete_names(records, num_to_delete=50):
return [name for name, _ in random.sample(records, min(num_to_delete, len(records)))]
def measure_insertion(structure_type, records, repeats=3):
times = []
for _ in range(repeats):
if structure_type == "LinkedList":
structure = None
insert_func = ll_insert
elif structure_type == "HashTable":
structure = ht_create(2000)
insert_func = ht_insert
elif structure_type == "BST":
structure = None
insert_func = bst_insert
else:
raise ValueError(f"Unknown structure: {structure_type}")
start = time.perf_counter()
for name, phone in records:
if structure_type == "HashTable":
insert_func(structure, name, phone)
else:
structure = insert_func(structure, name, phone)
end = time.perf_counter()
times.append(end - start)
return times
def measure_search(structure_type, structure, queries, repeats=3):
times = []
for _ in range(repeats):
start = time.perf_counter()
for name in queries:
if structure_type == "LinkedList":
ll_find(structure, name)
elif structure_type == "HashTable":
ht_find(structure, name)
elif structure_type == "BST":
bst_find(structure, name)
end = time.perf_counter()
times.append(end - start)
return times
def measure_deletion(structure_type, structure, names_to_delete, repeats=3):
times = []
for _ in range(repeats):
if structure_type == "LinkedList":
temp_structure = copy_linked_list(structure)
delete_func = ll_delete
elif structure_type == "HashTable":
temp_structure = structure.copy()
for i in range(len(temp_structure)):
if temp_structure[i]:
temp_structure[i] = copy_linked_list(temp_structure[i])
delete_func = ht_delete
elif structure_type == "BST":
temp_structure = copy_bst(structure)
delete_func = bst_delete
start = time.perf_counter()
for name in names_to_delete:
if structure_type == "HashTable":
delete_func(temp_structure, name)
else:
temp_structure = delete_func(temp_structure, name)
end = time.perf_counter()
times.append(end - start)
return times
def run_experiment(N=2000):
"""Запускает все эксперименты и возвращает результаты"""
print(f"Генерация тестовых данных (N={N})...")
records_shuffled, records_sorted = generate_test_data(N)
queries = get_test_queries(records_shuffled, num_existing=100, num_nonexisting=10)
delete_names = get_delete_names(records_shuffled, num_to_delete=50)
structures = ["LinkedList", "HashTable", "BST"]
modes = ["случайный", "отсортированный"]
results = []
print("\nНачало экспериментов:")
print("=" * 60)
for structure in structures:
print(f"\nТестирование {structure}...")
for mode in modes:
print(f" Режим: {mode}")
records = records_shuffled if mode == "случайный" else records_sorted
# Вставка
print(f" Измерение вставки...")
try:
insert_times = measure_insertion(structure, records, repeats=3)
avg_insert = sum(insert_times) / len(insert_times)
except RecursionError:
print(f" ОШИБКА: Превышена глубина рекурсии при вставке в {structure} для {mode} режима")
continue
print(f" Создание финальной структуры...")
if structure == "LinkedList":
final_structure = None
for name, phone in records:
final_structure = ll_insert(final_structure, name, phone)
elif structure == "HashTable":
final_structure = ht_create(2000)
for name, phone in records:
ht_insert(final_structure, name, phone)
elif structure == "BST":
final_structure = None
for name, phone in records:
final_structure = bst_insert(final_structure, name, phone)
print(f" Измерение поиска...")
search_times = measure_search(structure, final_structure, queries, repeats=3)
avg_search = sum(search_times) / len(search_times)
print(f" Измерение удаления...")
deletion_times = measure_deletion(structure, final_structure, delete_names, repeats=3)
avg_deletion = sum(deletion_times) / len(deletion_times)
results.append({
"Структура": structure,
"Режим": mode,
"Операция": "вставка",
"Замеры": insert_times,
"Среднее": avg_insert
})
results.append({
"Структура": structure,
"Режим": mode,
"Операция": "поиск",
"Замеры": search_times,
"Среднее": avg_search
})
results.append({
"Структура": structure,
"Режим": mode,
"Операция": "удаление",
"Замеры": deletion_times,
"Среднее": avg_deletion
})
print(f" Вставка: {avg_insert:.6f} сек")
print(f" Поиск: {avg_search:.6f} сек")
print(f" Удаление: {avg_deletion:.6f} сек")
return results
# ============================================================
# СОХРАНЕНИЕ РЕЗУЛЬТАТОВ В CSV
# ============================================================
import os
import csv
from datetime import datetime
def save_to_csv(results, filename="results.csv"):
save_dir = "/Users/mariiaos/2026-rff_mp/osipovamd/docs"
filepath = os.path.join(save_dir, filename)
with open(filepath, "w", newline="", encoding="utf-8") as f:
writer = csv.writer(f)
writer.writerow(["Структура", "Режим", "Операция", "Замер1", "Замер2", "Замер3", "Среднее"])
for res in results:
row = [
res["Структура"],
res["Режим"],
res["Операция"],
*[f"{t:.6f}" for t in res["Замеры"]],
f"{res['Среднее']:.6f}"
]
writer.writerow(row)
print(f"\nРезультаты сохранены в: {filepath}")
return filepath
def plot_results(results):
if not results:
print("Нет данных для построения графиков!")
return
plt.style.use('seaborn-v0_8-darkgrid')
fig, axes = plt.subplots(1, 3, figsize=(15, 5))
operations = ["вставка", "поиск", "удаление"]
structures = ["LinkedList", "HashTable", "BST"]
modes = ["случайный", "отсортированный"]
colors = {'LinkedList': '#FF6B6B', 'HashTable': '#4ECDC4', 'BST': '#45B7D1'}
for idx, operation in enumerate(operations):
ax = axes[idx]
x = np.arange(len(modes))
width = 0.25
multiplier = 0
for structure in structures:
values = []
for mode in modes:
found = False
for res in results:
if (res["Структура"] == structure and
res["Режим"] == mode and
res["Операция"] == operation):
values.append(res["Среднее"])
found = True
break
if not found:
values.append(0)
if max(values) > 0:
offset = width * multiplier
bars = ax.bar(x + offset, values, width, label=structure, color=colors[structure])
multiplier += 1
ax.set_xlabel('Режим данных', fontsize=12)
ax.set_ylabel('Время (секунды)', fontsize=12)
ax.set_title(f'{operation.capitalize()}', fontsize=14, fontweight='bold')
ax.set_xticks(x + width)
ax.set_xticklabels(modes)
ax.legend(loc='upper left')
ax.grid(True, alpha=0.3)
plt.suptitle('Сравнение производительности структур данных',
fontsize=16, fontweight='bold')
plt.tight_layout()
plt.savefig('performance_comparison.png', dpi=300, bbox_inches='tight')
plt.show()
print("\nГрафик сохранён как 'performance_comparison.png'")
if __name__ == "__main__":
print("=" * 60)
print("ТЕСТИРОВАНИЕ ПРОИЗВОДИТЕЛЬНОСТИ СТРУКТУР ДАННЫХ")
print("=" * 60)
results = run_experiment(N=1000)
save_to_csv(results)
if results:
print("\nПостроение графиков...")
plot_results(results)
print("\n" + "=" * 60)
print("СВОДНАЯ ТАБЛИЦА РЕЗУЛЬТАТОВ (среднее время в секундах)")
print("=" * 60)
print(f"{'Структура':<12} {'Режим':<12} {'Вставка':<10} {'Поиск':<10} {'Удаление':<10}")
print("-" * 60)
for structure in ["LinkedList", "HashTable", "BST"]:
for mode in ["случайный", "отсортированный"]:
insert_time = search_time = delete_time = 0
for res in results:
if res["Структура"] == structure and res["Режим"] == mode:
if res["Операция"] == "вставка":
insert_time = res["Среднее"]
elif res["Операция"] == "поиск":
search_time = res["Среднее"]
elif res["Операция"] == "удаление":
delete_time = res["Среднее"]
if insert_time > 0 or search_time > 0 or delete_time > 0:
print(f"{structure:<12} {mode:<12} {insert_time:<10.6f} {search_time:<10.6f} {delete_time:<10.6f}")
else:
print("\nЭксперимент не дал результатов из-за ошибок.")
print("\nЭксперимент завершён!")

BIN
osipovamd/docs/~$Task1.docx Normal file

Binary file not shown.