forked from UNN/2026-rff_mp
[13] Final. All is complete
This commit is contained in:
parent
83e323fff6
commit
41004bcb8a
BIN
ShapovalovKA/docs/1st_task_analysis.docx
Normal file
BIN
ShapovalovKA/docs/1st_task_analysis.docx
Normal file
Binary file not shown.
BIN
ShapovalovKA/docs/2nd_task_analysis.docx
Normal file
BIN
ShapovalovKA/docs/2nd_task_analysis.docx
Normal file
Binary file not shown.
48
ShapovalovKA/docs/data/1Task/res.py
Normal file
48
ShapovalovKA/docs/data/1Task/res.py
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
import csv
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
array_arr = []
|
||||
array_list = []
|
||||
array_hash = []
|
||||
array_bin = []
|
||||
|
||||
with open('results.csv', 'r', encoding='utf-8-sig') as file:
|
||||
reader = csv.reader(file, delimiter=';')
|
||||
next(reader) # пропускаем заголовок
|
||||
|
||||
values = []
|
||||
for row in reader:
|
||||
values.append(float(row[3]))
|
||||
|
||||
array_arr = values[0:4]
|
||||
array_list = values[4:8]
|
||||
array_hash = values[8:12]
|
||||
array_bin = values[12:16]
|
||||
|
||||
print(f"array_arr : {array_arr}")
|
||||
print(f"array_list: {array_list}")
|
||||
print(f"array_hash: {array_hash}")
|
||||
print(f"array_bin : {array_bin}")
|
||||
|
||||
l = [1, 2, 3, 4]
|
||||
|
||||
#визуализация без дерева
|
||||
plt.plot(l, array_arr, label = 'Array', c='black')
|
||||
plt.plot(l, array_list, label = 'Linked list', c='blue')
|
||||
plt.plot(l, array_hash, label = 'Hash table', c='orange')
|
||||
plt.ylabel('array') #название по y
|
||||
plt.xlabel('l') #название по x
|
||||
plt.legend(loc='upper center', bbox_to_anchor=(0.5, 1.15), ncol = 3)
|
||||
plt.savefig('t1p1.png', dpi=300, bbox_inches='tight') #сохранение в файле
|
||||
plt.show()
|
||||
|
||||
#визуализация с деревом
|
||||
plt.plot(l, array_arr, label = 'Array', c='black')
|
||||
plt.plot(l, array_list, label = 'Linked list', c='blue')
|
||||
plt.plot(l, array_hash, label = 'Hash table', c='orange')
|
||||
plt.plot(l, array_bin, label = 'Binary tree', c='red')
|
||||
plt.ylabel('array') #название по y
|
||||
plt.xlabel('l') #название по x
|
||||
plt.legend(loc='upper center', bbox_to_anchor=(0.5, 1.15), ncol = 4)
|
||||
plt.savefig('t1p2.png', dpi=300, bbox_inches='tight') #сохранение в файле
|
||||
plt.show()
|
||||
9
ShapovalovKA/docs/data/1Task/results.csv
Normal file
9
ShapovalovKA/docs/data/1Task/results.csv
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
Структура;Режим;Операция;Время (сек)
|
||||
Array;случайный;вставка (в начало);0.06431880006566644
|
||||
Array;отсортированный;вставка (в начало);0.06380272014066576
|
||||
Array;любой;поиск 110 записей;0.07721293987706304
|
||||
Array;любой;удаление 50 записей (среднее);0.0018548803813755513
|
||||
Linked list;случайный;вставка (в начало);0.01246960014104843
|
||||
Linked list;отсортированный;вставка (в начало);0.007890580128878355
|
||||
Linked list;любой;поиск 110 записей;0.23582311999052763
|
||||
Linked list;любой;удаление 50 записей (среднее);0.0023578427862375973
|
||||
|
212
ShapovalovKA/docs/data/1Task/t1_1.py
Normal file
212
ShapovalovKA/docs/data/1Task/t1_1.py
Normal file
|
|
@ -0,0 +1,212 @@
|
|||
import random
|
||||
import time
|
||||
import csv
|
||||
|
||||
# ---------- Реализация связного списка ----------
|
||||
def ll_insert_begin(head, name, phone):
|
||||
# Вставка узла в начало списка. Возвращает новую голову.
|
||||
new_node = {'name': name, 'phone': phone, 'next': head}
|
||||
return new_node
|
||||
|
||||
def ll_find(head, name):
|
||||
# Поиск телефона по имени. Возвращает phone или None.
|
||||
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']
|
||||
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 array_insert_measure(records, sorted_flag=False):
|
||||
# Вставка записей в начало массива. Возвращает время.
|
||||
arr = []
|
||||
start = time.perf_counter()
|
||||
if sorted_flag:
|
||||
# records уже отсортированы
|
||||
for item in records:
|
||||
arr.insert(0, item)
|
||||
else:
|
||||
for item in records:
|
||||
arr.insert(0, item)
|
||||
end = time.perf_counter()
|
||||
return end - start
|
||||
|
||||
def array_find_measure(records, test_names):
|
||||
# Поиск в массиве: линейный перебор.
|
||||
start = time.perf_counter()
|
||||
for name in test_names:
|
||||
for rec in records:
|
||||
if rec[0] == name:
|
||||
break
|
||||
end = time.perf_counter()
|
||||
return end - start
|
||||
|
||||
def array_delete_measure(records, delete_names):
|
||||
# Удаление из массива через создание нового списка (как в оригинале).
|
||||
times = []
|
||||
for name in delete_names:
|
||||
start = time.perf_counter()
|
||||
records = [rec for rec in records if rec[0] != name]
|
||||
end = time.perf_counter()
|
||||
times.append(end - start)
|
||||
return sum(times) / len(times) if times else 0
|
||||
|
||||
|
||||
|
||||
# ---------- Измерения для связного списка ----------
|
||||
def linked_insert_measure(records, sorted_flag=False):
|
||||
# Вставка записей в начало связного списка. Возвращает время.
|
||||
head = None
|
||||
start = time.perf_counter()
|
||||
# Если sorted_flag == True, records уже отсортированы, но для связного списка
|
||||
# вставка в начало всегда O(1), порядок не влияет на время.
|
||||
for name, phone in records:
|
||||
head = ll_insert_begin(head, name, phone)
|
||||
end = time.perf_counter()
|
||||
return end - start
|
||||
|
||||
def linked_find_measure(head, test_names):
|
||||
# Поиск в связном списке.
|
||||
start = time.perf_counter()
|
||||
for name in test_names:
|
||||
ll_find(head, name)
|
||||
end = time.perf_counter()
|
||||
return end - start
|
||||
|
||||
def linked_delete_measure(head, delete_names):
|
||||
# Удаление из связного списка.
|
||||
times = []
|
||||
for name in delete_names:
|
||||
start = time.perf_counter()
|
||||
head = ll_delete(head, name)
|
||||
end = time.perf_counter()
|
||||
times.append(end - start)
|
||||
return sum(times) / len(times) if times else 0
|
||||
|
||||
|
||||
|
||||
# ---------- Основная функция эксперимента ----------
|
||||
def main():
|
||||
N = 10000
|
||||
# Генерация тестовых данных
|
||||
records = []
|
||||
for i in range(N):
|
||||
name = f"User_{i:05d}"
|
||||
phone = f"8{random.randint(9000000000, 9999999999)}"
|
||||
records.append((name, phone))
|
||||
|
||||
records_shuffled = records.copy()
|
||||
random.shuffle(records_shuffled)
|
||||
records_sorted = sorted(records, key=lambda x: x[0])
|
||||
|
||||
# Имена для поиска (100 существующих + 10 несуществующих)
|
||||
existing_names = random.sample([rec[0] for rec in records], 100)
|
||||
non_existing = [f"None_{i}" for i in range(10)]
|
||||
test_names = existing_names + non_existing
|
||||
|
||||
# Имена для удаления (50 случайных)
|
||||
delete_names = random.sample([rec[0] for rec in records], 50)
|
||||
|
||||
# Результаты будем собирать в список списков
|
||||
results = [["Структура", "Режим", "Операция", "Время (сек)"]]
|
||||
|
||||
|
||||
|
||||
# ----- Массив -----
|
||||
# Вставка (случайный порядок)
|
||||
arr_time_shuffled = 0.0
|
||||
arr_time_sorted = 0.0
|
||||
for _ in range(5):
|
||||
arr_time_shuffled += array_insert_measure(records_shuffled, sorted_flag=False)
|
||||
arr_time_sorted += array_insert_measure(records_sorted, sorted_flag=True)
|
||||
results.append(["Array", "случайный", "вставка (в начало)", arr_time_shuffled / 5])
|
||||
results.append(["Array", "отсортированный", "вставка (в начало)", arr_time_sorted / 5])
|
||||
|
||||
# Поиск
|
||||
find_time = 0.0
|
||||
for _ in range(5):
|
||||
find_time += array_find_measure(records, test_names)
|
||||
results.append(["Array", "любой", "поиск 110 записей", find_time / 5])
|
||||
|
||||
# Удаление
|
||||
del_time = 0.0
|
||||
for _ in range(5):
|
||||
del_time += array_delete_measure(records.copy(), delete_names)
|
||||
results.append(["Array", "любой", "удаление 50 записей (среднее)", del_time / 5])
|
||||
|
||||
|
||||
|
||||
# ----- Связный список -----
|
||||
# Вставка
|
||||
ll_time_shuffled = 0.0
|
||||
ll_time_sorted = 0.0
|
||||
for _ in range(5):
|
||||
ll_time_shuffled += linked_insert_measure(records_shuffled)
|
||||
ll_time_sorted += linked_insert_measure(records_sorted)
|
||||
results.append(["Linked list", "случайный", "вставка (в начало)", ll_time_shuffled / 5])
|
||||
results.append(["Linked list", "отсортированный", "вставка (в начало)", ll_time_sorted / 5])
|
||||
|
||||
# Поиск (предварительно строим список)
|
||||
head = None
|
||||
for name, phone in records:
|
||||
head = ll_insert_begin(head, name, phone)
|
||||
find_time_ll = 0.0
|
||||
for _ in range(5):
|
||||
find_time_ll += linked_find_measure(head, test_names)
|
||||
results.append(["Linked list", "любой", "поиск 110 записей", find_time_ll / 5])
|
||||
|
||||
# Удаление (копируем список для каждого замера)
|
||||
del_time_ll = 0.0
|
||||
for _ in range(5):
|
||||
# Строим новую копию списка
|
||||
h = None
|
||||
for name, phone in records:
|
||||
h = ll_insert_begin(h, name, phone)
|
||||
del_time_ll += linked_delete_measure(h, delete_names)
|
||||
results.append(["Linked list", "любой", "удаление 50 записей (среднее)", del_time_ll / 5])
|
||||
|
||||
# ----- Вывод результатов в единый столбец -----
|
||||
print("\nРезультаты экспериментов (время в секундах):\n")
|
||||
# Определяем максимальную ширину первого столбца для красивого выравнивания
|
||||
col_widths = [max(len(str(row[i])) for row in results) for i in range(4)]
|
||||
for row in results:
|
||||
print(f"{row[0]:<{col_widths[0]}} {row[1]:<{col_widths[1]}} "
|
||||
f"{row[2]:<{col_widths[2]}} {row[3]:<{col_widths[3]}}")
|
||||
|
||||
# ----- Запись результатов в CSV-файл -----
|
||||
with open('results.csv', 'w', newline='', encoding='utf-8-sig') as csvfile:
|
||||
writer = csv.writer(csvfile, delimiter = ';')
|
||||
writer.writerows(results)
|
||||
|
||||
print("\nРезультаты сохранены в файл 'results.csv'.")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
185
ShapovalovKA/docs/data/1Task/t1_2.py
Normal file
185
ShapovalovKA/docs/data/1Task/t1_2.py
Normal file
|
|
@ -0,0 +1,185 @@
|
|||
import random
|
||||
import time
|
||||
import csv
|
||||
import os
|
||||
|
||||
# --------------------- Реализация связного списка (взята из t1_1) ---------------------
|
||||
def ll_insert_begin(head, name, phone):
|
||||
# Вставка узла в начало списка. Возвращает новую голову.
|
||||
new_node = {'name': name, 'phone': phone, 'next': head}
|
||||
return new_node
|
||||
|
||||
def ll_find(head, name):
|
||||
# Поиск телефона по имени. Возвращает phone или None.
|
||||
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']
|
||||
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
|
||||
|
||||
# --------------------- Реализация хеш-таблицы ---------------------
|
||||
class HashTable:
|
||||
def __init__(self, size=2000):
|
||||
self.size = size
|
||||
self.buckets = [None] * size # каждый bucket — голова связного списка
|
||||
|
||||
def _hash(self, name):
|
||||
# Простая хеш-функция: сумма кодов символов по модулю размера.
|
||||
return sum(ord(ch) for ch in name) % self.size
|
||||
|
||||
def insert(self, name, phone):
|
||||
index = self._hash(name)
|
||||
# Вставляем в начало связного списка в данном bucket'е
|
||||
self.buckets[index] = ll_insert_begin(self.buckets[index], name, phone)
|
||||
|
||||
def find(self, name):
|
||||
index = self._hash(name)
|
||||
return ll_find(self.buckets[index], name)
|
||||
|
||||
def delete(self, name):
|
||||
index = self._hash(name)
|
||||
self.buckets[index] = ll_delete(self.buckets[index], name)
|
||||
|
||||
def list_all(self):
|
||||
# Собирает все записи из всех bucket'ов и сортирует по имени.
|
||||
all_records = []
|
||||
for head in self.buckets:
|
||||
current = head
|
||||
while current:
|
||||
all_records.append((current['name'], current['phone']))
|
||||
current = current['next']
|
||||
all_records.sort(key=lambda x: x[0])
|
||||
return all_records
|
||||
|
||||
# --------------------- Функции измерений ---------------------
|
||||
def generate_data(N=10000):
|
||||
records = []
|
||||
for i in range(N):
|
||||
name = f"User_{i:05d}"
|
||||
phone = f"8{random.randint(9000000000, 9999999999)}"
|
||||
records.append((name, phone))
|
||||
return records
|
||||
|
||||
def measure_insert(records, sort_order='random'):
|
||||
# Измеряет время вставки в хеш-таблицу.
|
||||
# sort_order: 'random' или 'sorted' — порядок передаваемых записей.
|
||||
ht = HashTable(size=2000)
|
||||
start = time.perf_counter()
|
||||
for name, phone in records:
|
||||
ht.insert(name, phone)
|
||||
end = time.perf_counter()
|
||||
return end - start
|
||||
|
||||
def measure_find(records, test_names):
|
||||
# Поиск 110 записей в уже заполненной хеш-таблице.
|
||||
ht = HashTable(size=2000)
|
||||
for name, phone in records:
|
||||
ht.insert(name, phone)
|
||||
start = time.perf_counter()
|
||||
for name in test_names:
|
||||
ht.find(name)
|
||||
end = time.perf_counter()
|
||||
return end - start
|
||||
|
||||
def measure_delete(records, delete_names):
|
||||
# Удаление 50 записей из хеш-таблицы (среднее время одного удаления).
|
||||
times = []
|
||||
for name in delete_names:
|
||||
ht = HashTable(size=2000)
|
||||
for n, p in records:
|
||||
ht.insert(n, p)
|
||||
start = time.perf_counter()
|
||||
ht.delete(name)
|
||||
end = time.perf_counter()
|
||||
times.append(end - start)
|
||||
return sum(times) / len(times)
|
||||
|
||||
# --------------------- Основная функция ---------------------
|
||||
def main():
|
||||
N = 10000
|
||||
records = generate_data(N)
|
||||
|
||||
# Перемешанные и отсортированные копии
|
||||
records_shuffled = records.copy()
|
||||
random.shuffle(records_shuffled)
|
||||
records_sorted = sorted(records, key=lambda x: x[0])
|
||||
|
||||
# Имена для поиска (100 существующих + 10 несуществующих)
|
||||
existing_names = random.sample([rec[0] for rec in records], 100)
|
||||
non_existing = [f"None_{i}" for i in range(10)]
|
||||
test_names = existing_names + non_existing
|
||||
|
||||
# Имена для удаления (50 случайных)
|
||||
delete_names = random.sample([rec[0] for rec in records], 50)
|
||||
|
||||
# Замеры (по 5 повторений)
|
||||
insert_shuffled_avg = 0.0
|
||||
insert_sorted_avg = 0.0
|
||||
find_avg = 0.0
|
||||
delete_avg = 0.0
|
||||
|
||||
repeats = 5
|
||||
for _ in range(repeats):
|
||||
insert_shuffled_avg += measure_insert(records_shuffled, 'random')
|
||||
insert_sorted_avg += measure_insert(records_sorted, 'sorted')
|
||||
find_avg += measure_find(records, test_names)
|
||||
delete_avg += measure_delete(records, delete_names)
|
||||
|
||||
insert_shuffled_avg /= repeats
|
||||
insert_sorted_avg /= repeats
|
||||
find_avg /= repeats
|
||||
delete_avg /= repeats
|
||||
|
||||
# Подготовка строк для CSV
|
||||
new_rows = [
|
||||
["Hash table", "случайный", "вставка (в начало)", insert_shuffled_avg],
|
||||
["Hash table", "отсортированный", "вставка (в начало)", insert_sorted_avg],
|
||||
["Hash table", "любой", "поиск 110 записей", find_avg],
|
||||
["Hash table", "любой", "удаление 50 записей (среднее)", delete_avg]
|
||||
]
|
||||
|
||||
# Определяем имя CSV-файла (там же, где и t1_1.py)
|
||||
csv_filename = "results.csv"
|
||||
file_exists = os.path.isfile(csv_filename)
|
||||
|
||||
# Запись в CSV (добавление)
|
||||
with open(csv_filename, 'a', newline='', encoding='utf-8-sig') as f:
|
||||
writer = csv.writer(f, delimiter=';')
|
||||
# Если файл только что создан, сначала запишем заголовок
|
||||
if not file_exists:
|
||||
writer.writerow(["Структура", "Режим", "Операция", "Время (сек)"])
|
||||
writer.writerows(new_rows)
|
||||
|
||||
print("Результаты для хеш-таблицы добавлены в", csv_filename)
|
||||
print(f"Среднее время вставки (случ. порядок): {insert_shuffled_avg:.6f} сек")
|
||||
print(f"Среднее время вставки (отсорт.): {insert_sorted_avg:.6f} сек")
|
||||
print(f"Среднее время поиска 110 записей: {find_avg:.6f} сек")
|
||||
print(f"Среднее время удаления 50 записей: {delete_avg:.6f} сек")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
211
ShapovalovKA/docs/data/1Task/t1_3.py
Normal file
211
ShapovalovKA/docs/data/1Task/t1_3.py
Normal file
|
|
@ -0,0 +1,211 @@
|
|||
import random
|
||||
import time
|
||||
import csv
|
||||
import os
|
||||
|
||||
# --------------------- Реализация бинарного дерева поиска (итеративная) ---------------------
|
||||
def bst_insert(root, name, phone):
|
||||
#Итеративная вставка. Возвращает корень.
|
||||
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
|
||||
else:
|
||||
current = current['left']
|
||||
elif name > current['name']:
|
||||
if current['right'] is None:
|
||||
current['right'] = new_node
|
||||
break
|
||||
else:
|
||||
current = current['right']
|
||||
else: # имя уже существует — обновляем телефон
|
||||
current['phone'] = phone
|
||||
break
|
||||
return root
|
||||
|
||||
def bst_find(root, name):
|
||||
#Итеративный поиск. Возвращает phone или None.
|
||||
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):
|
||||
#Возвращает узел с минимальным ключом в поддереве.
|
||||
while node['left']:
|
||||
node = node['left']
|
||||
return node
|
||||
|
||||
def bst_delete(root, name):
|
||||
#Итеративное удаление. Возвращает новый корень.
|
||||
# Сначала найдём удаляемый узел и его родителя
|
||||
parent = None
|
||||
current = root
|
||||
while current and current['name'] != name:
|
||||
parent = current
|
||||
if name < current['name']:
|
||||
current = current['left']
|
||||
else:
|
||||
current = current['right']
|
||||
if current is None: # узел не найден
|
||||
return root
|
||||
|
||||
# Случай 1: нет левого потомка
|
||||
if current['left'] is None:
|
||||
child = current['right']
|
||||
# Случай 2: нет правого потомка
|
||||
elif current['right'] is None:
|
||||
child = current['left']
|
||||
# Случай 3: два потомка
|
||||
else:
|
||||
# Находим минимальный узел в правом поддереве (преемник)
|
||||
min_parent = current
|
||||
min_node = current['right']
|
||||
while min_node['left']:
|
||||
min_parent = min_node
|
||||
min_node = min_node['left']
|
||||
# Копируем данные из min_node в current
|
||||
current['name'], current['phone'] = min_node['name'], min_node['phone']
|
||||
# Удаляем min_node (у него нет левого потомка)
|
||||
if min_parent['left'] == min_node:
|
||||
min_parent['left'] = min_node['right']
|
||||
else:
|
||||
min_parent['right'] = min_node['right']
|
||||
return root
|
||||
|
||||
# Подсоединяем child к parent
|
||||
if parent is None:
|
||||
return child
|
||||
if parent['left'] == current:
|
||||
parent['left'] = child
|
||||
else:
|
||||
parent['right'] = child
|
||||
return root
|
||||
|
||||
def bst_list_all(root):
|
||||
#Итеративный симметричный обход (inorder) без рекурсии, используя стек.
|
||||
result = []
|
||||
stack = []
|
||||
current = root
|
||||
while stack or current:
|
||||
while current:
|
||||
stack.append(current)
|
||||
current = current['left']
|
||||
current = stack.pop()
|
||||
result.append((current['name'], current['phone']))
|
||||
current = current['right']
|
||||
return result
|
||||
|
||||
# --------------------- Функции измерений ---------------------
|
||||
def generate_data(N=10000):
|
||||
records = []
|
||||
for i in range(N):
|
||||
name = f"User_{i:05d}"
|
||||
phone = f"8{random.randint(9000000000, 9999999999)}"
|
||||
records.append((name, phone))
|
||||
return records
|
||||
|
||||
def measure_insert(records):
|
||||
root = None
|
||||
start = time.perf_counter()
|
||||
for name, phone in records:
|
||||
root = bst_insert(root, name, phone)
|
||||
end = time.perf_counter()
|
||||
return end - start
|
||||
|
||||
def measure_find(records, test_names):
|
||||
root = None
|
||||
for name, phone in records:
|
||||
root = bst_insert(root, name, phone)
|
||||
start = time.perf_counter()
|
||||
for name in test_names:
|
||||
bst_find(root, name)
|
||||
end = time.perf_counter()
|
||||
return end - start
|
||||
|
||||
def measure_delete(records, delete_names):
|
||||
times = []
|
||||
for name in delete_names:
|
||||
root = None
|
||||
for n, p in records:
|
||||
root = bst_insert(root, n, p)
|
||||
start = time.perf_counter()
|
||||
root = bst_delete(root, name)
|
||||
end = time.perf_counter()
|
||||
times.append(end - start)
|
||||
return sum(times) / len(times)
|
||||
|
||||
def main():
|
||||
N = 10000
|
||||
records = generate_data(N)
|
||||
|
||||
records_shuffled = records.copy()
|
||||
random.shuffle(records_shuffled)
|
||||
records_sorted = sorted(records, key=lambda x: x[0])
|
||||
|
||||
existing_names = random.sample([rec[0] for rec in records], 100)
|
||||
non_existing = [f"None_{i}" for i in range(10)]
|
||||
test_names = existing_names + non_existing
|
||||
|
||||
delete_names = random.sample([rec[0] for rec in records], 50)
|
||||
|
||||
insert_shuffled_avg = 0.0
|
||||
insert_sorted_avg = 0.0
|
||||
find_avg = 0.0
|
||||
delete_avg = 0.0
|
||||
|
||||
repeats = 5
|
||||
for _ in range(repeats):
|
||||
insert_shuffled_avg += measure_insert(records_shuffled)
|
||||
insert_sorted_avg += measure_insert(records_sorted)
|
||||
find_avg += measure_find(records, test_names)
|
||||
delete_avg += measure_delete(records, delete_names)
|
||||
|
||||
insert_shuffled_avg /= repeats
|
||||
insert_sorted_avg /= repeats
|
||||
find_avg /= repeats
|
||||
delete_avg /= repeats
|
||||
|
||||
new_rows = [
|
||||
["Binary tree", "случайный", "вставка (корень)", insert_shuffled_avg],
|
||||
["Binary tree", "отсортированный", "вставка (корень)", insert_sorted_avg],
|
||||
["Binary tree", "любой", "поиск 110 записей", find_avg],
|
||||
["Binary tree", "любой", "удаление 50 записей (среднее)", delete_avg]
|
||||
]
|
||||
|
||||
csv_filename = "results.csv"
|
||||
file_exists = os.path.isfile(csv_filename)
|
||||
need_header = False
|
||||
if file_exists:
|
||||
with open(csv_filename, 'r', encoding='utf-8-sig') as f:
|
||||
first_line = f.readline()
|
||||
if not first_line.startswith("Структура"):
|
||||
need_header = True
|
||||
else:
|
||||
need_header = True
|
||||
|
||||
with open(csv_filename, 'a', newline='', encoding='utf-8-sig') as f:
|
||||
writer = csv.writer(f, delimiter=';')
|
||||
if need_header:
|
||||
writer.writerow(["Структура", "Режим", "Операция", "Время (сек)"])
|
||||
writer.writerows(new_rows)
|
||||
|
||||
print("Результаты для двоичного дерева поиска добавлены в", csv_filename)
|
||||
print(f"Среднее время вставки (случ. порядок): {insert_shuffled_avg:.6f} сек")
|
||||
print(f"Среднее время вставки (отсорт.): {insert_sorted_avg:.6f} сек")
|
||||
print(f"Среднее время поиска 110 записей: {find_avg:.6f} сек")
|
||||
print(f"Среднее время удаления 50 записей: {delete_avg:.6f} сек")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
BIN
ShapovalovKA/docs/data/1Task/t1p1.png
Normal file
BIN
ShapovalovKA/docs/data/1Task/t1p1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 107 KiB |
BIN
ShapovalovKA/docs/data/1Task/t1p2.png
Normal file
BIN
ShapovalovKA/docs/data/1Task/t1p2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 70 KiB |
2
ShapovalovKA/docs/data/1Task/Порядок использования.txt
Normal file
2
ShapovalovKA/docs/data/1Task/Порядок использования.txt
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
t1_1.py -> t1_2.py -> t1_3.py
|
||||
-> res.py
|
||||
BIN
ShapovalovKA/docs/data/2Task/efficiency_ratio.png
Normal file
BIN
ShapovalovKA/docs/data/2Task/efficiency_ratio.png
Normal file
Binary file not shown.
21
ShapovalovKA/docs/data/2Task/experiment_results.csv
Normal file
21
ShapovalovKA/docs/data/2Task/experiment_results.csv
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
maze_type;strategy;avg_time_ms;std_time_ms;avg_visited;avg_path_len;path_found
|
||||
small_10x10_simple;BFS;0.187180;0.026335;19.000000;19.000000;True
|
||||
small_10x10_simple;DFS;0.167600;0.006841;19.000000;19.000000;True
|
||||
small_10x10_simple;A*;0.262300;0.029262;19.000000;19.000000;True
|
||||
small_10x10_simple;Dijkstra;0.260840;0.008608;19.000000;19.000000;True
|
||||
medium_50x50_deadends;BFS;3.563500;0.053603;380.000000;99.000000;True
|
||||
medium_50x50_deadends;DFS;3.618520;0.082922;270.000000;219.000000;True
|
||||
medium_50x50_deadends;A*;4.865660;0.017732;334.000000;99.000000;True
|
||||
medium_50x50_deadends;Dijkstra;6.019060;0.037679;380.000000;99.000000;True
|
||||
large_100x100_complex;BFS;8.644360;0.236037;886.000000;199.000000;True
|
||||
large_100x100_complex;DFS;13.781640;2.087117;697.000000;511.000000;True
|
||||
large_100x100_complex;A*;12.167040;0.334660;774.000000;199.000000;True
|
||||
large_100x100_complex;Dijkstra;14.365940;0.236778;886.000000;199.000000;True
|
||||
empty_50x50;BFS;24.584480;0.184147;2500.000000;99.000000;True
|
||||
empty_50x50;DFS;182.315780;4.196306;2451.000000;2451.000000;True
|
||||
empty_50x50;A*;42.602980;0.184895;2500.000000;99.000000;True
|
||||
empty_50x50;Dijkstra;43.213780;0.745780;2500.000000;99.000000;True
|
||||
no_exit_50x50;BFS;25.037680;0.572634;2496.000000;0.000000;False
|
||||
no_exit_50x50;DFS;191.040920;3.180626;2496.000000;0.000000;False
|
||||
no_exit_50x50;A*;42.158280;0.396219;2496.000000;0.000000;False
|
||||
no_exit_50x50;Dijkstra;42.499100;0.482887;2496.000000;0.000000;False
|
||||
|
Gitea Version: 1.22.0 |
