[1] task1
This commit is contained in:
parent
0d86929b62
commit
053e635cda
71
nehoroshevaa/Task 1/code/BinaryTree.py
Normal file
71
nehoroshevaa/Task 1/code/BinaryTree.py
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
#Узел — словарь: {'name': 'Имя', 'phone': '123', 'left': None, 'right': None}.
|
||||
def bst_insert(root, name, phone):
|
||||
#рекурсивно или итеративно вставляет, возвращает новый корень (если корень меняется).
|
||||
if root is None:
|
||||
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 root is None:
|
||||
return None
|
||||
|
||||
if name == root['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 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):
|
||||
# центрированный обход (рекурсивно собирает записи в отсортированном порядке).
|
||||
if root is None:
|
||||
return []
|
||||
|
||||
return (
|
||||
bst_list_all(root['left']) +
|
||||
[(root['name'], root['phone'])] +
|
||||
bst_list_all(root['right'])
|
||||
)
|
||||
56
nehoroshevaa/Task 1/code/HashTable.py
Normal file
56
nehoroshevaa/Task 1/code/HashTable.py
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
#Аналогично ht_find, ht_delete, ht_list_all (последняя собирает все записи из всех бакетов и сортирует).
|
||||
from code.LinkedList import *
|
||||
|
||||
def create_buckets(size=1000):
|
||||
return [None] * size
|
||||
|
||||
def hash_function(name, bucket_size):
|
||||
hash_value = 0
|
||||
|
||||
for char in name:
|
||||
hash_value = (hash_value * 31 + ord(char)) % bucket_size
|
||||
|
||||
return hash_value
|
||||
|
||||
def ht_insert(buckets, name, phone):
|
||||
#вычисляет индекс, вызывает ll_insert для соответствующего бакета.
|
||||
if buckets is None:
|
||||
buckets = create_buckets()
|
||||
|
||||
index = hash_function(name, len(buckets))
|
||||
buckets[index] = ll_insert(buckets[index], name, phone)
|
||||
|
||||
return buckets
|
||||
|
||||
def ht_find(buckets, name):
|
||||
if not buckets:
|
||||
return None
|
||||
|
||||
index = hash_function(name, len(buckets))
|
||||
return ll_find(buckets[index], name)
|
||||
|
||||
def ht_delete(buckets, name):
|
||||
if not buckets:
|
||||
return buckets
|
||||
|
||||
index = hash_function(name, len(buckets))
|
||||
buckets[index] = ll_delete(buckets[index], name)
|
||||
|
||||
return buckets
|
||||
|
||||
def ht_list_all(buckets):
|
||||
if not buckets:
|
||||
return []
|
||||
|
||||
records = []
|
||||
|
||||
for bucket in buckets:
|
||||
current = bucket
|
||||
|
||||
while current is not None:
|
||||
records.append((current['name'], current['phone']))
|
||||
current = current['next']
|
||||
|
||||
records.sort(key=lambda x: x[0])
|
||||
|
||||
return records
|
||||
62
nehoroshevaa/Task 1/code/LinkedList.py
Normal file
62
nehoroshevaa/Task 1/code/LinkedList.py
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
def ll_insert(head, name, phone):
|
||||
#проходит до конца (или сразу добавляет в конец) и возвращает новую голову (если вставка в начало) или изменяет список по ссылке. Удобнее возвращать новую голову, если вставка может быть в начало.
|
||||
if head is None:
|
||||
return {'name': name, 'phone': phone, 'next': None}
|
||||
|
||||
current = head
|
||||
|
||||
while current is not None:
|
||||
if current['name'] == name:
|
||||
current['phone'] = phone
|
||||
return head
|
||||
|
||||
if current['next'] is None:
|
||||
current['next'] = {'name': name, 'phone': phone, 'next': None}
|
||||
return head
|
||||
|
||||
current = current['next']
|
||||
|
||||
|
||||
def ll_find(head, name):
|
||||
# ищет узел, возвращает телефон или None.
|
||||
current = head
|
||||
|
||||
while current is not None:
|
||||
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'] is not None:
|
||||
if current['next']['name'] == name:
|
||||
current['next'] = current['next']['next']
|
||||
return head
|
||||
current = current['next']
|
||||
|
||||
return head
|
||||
|
||||
|
||||
def ll_list_all(head):
|
||||
#собирает все записи в список и сортирует (сортировка вынесена отдельно).
|
||||
result = []
|
||||
current = head
|
||||
|
||||
while current is not None:
|
||||
result.append((current['name'], current['phone']))
|
||||
current = current['next']
|
||||
|
||||
result.sort(key=lambda x: x[0])
|
||||
|
||||
return result
|
||||
0
nehoroshevaa/Task 1/code/__init__.py
Normal file
0
nehoroshevaa/Task 1/code/__init__.py
Normal file
138
nehoroshevaa/Task 1/exp.py
Normal file
138
nehoroshevaa/Task 1/exp.py
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
import sys
|
||||
sys.setrecursionlimit(20000)
|
||||
import time
|
||||
import random
|
||||
import csv
|
||||
|
||||
from code.LinkedList import *
|
||||
from code.HashTable import *
|
||||
from code.BinaryTree import *
|
||||
|
||||
|
||||
|
||||
def generate_data(n=10000):
|
||||
return [(f"User_{i:05d}", f"+7-900-{i:05d}") for i in range(n)]
|
||||
|
||||
|
||||
def prepare_data(n=10000):
|
||||
data = generate_data(n)
|
||||
|
||||
shuffled = data[:]
|
||||
random.shuffle(shuffled)
|
||||
|
||||
sorted_data = sorted(data, key=lambda x: x[0])
|
||||
|
||||
return shuffled, sorted_data
|
||||
|
||||
|
||||
|
||||
def measure_find(find_func, obj, data):
|
||||
exist = random.sample([x[0] for x in data], 100)
|
||||
fake = [f"None_{i}" for i in range(10)]
|
||||
names = exist + fake
|
||||
|
||||
start = time.perf_counter()
|
||||
|
||||
for name in names:
|
||||
find_func(obj, name)
|
||||
|
||||
return time.perf_counter() - start
|
||||
|
||||
|
||||
|
||||
def measure_delete(delete_func, obj, data):
|
||||
names = random.sample([x[0] for x in data], 50)
|
||||
|
||||
start = time.perf_counter()
|
||||
|
||||
for name in names:
|
||||
obj = delete_func(obj, name)
|
||||
|
||||
return time.perf_counter() - start
|
||||
|
||||
|
||||
|
||||
def test_linked_list(data):
|
||||
head = None
|
||||
|
||||
start = time.perf_counter()
|
||||
for name, phone in data:
|
||||
head = ll_insert(head, name, phone)
|
||||
insert_time = time.perf_counter() - start
|
||||
|
||||
find_time = measure_find(ll_find, head, data)
|
||||
delete_time = measure_delete(ll_delete, head, data)
|
||||
|
||||
return insert_time, find_time, delete_time
|
||||
|
||||
|
||||
|
||||
def test_hash_table(data):
|
||||
buckets = create_buckets(1000)
|
||||
|
||||
start = time.perf_counter()
|
||||
for name, phone in data:
|
||||
ht_insert(buckets, name, phone)
|
||||
insert_time = time.perf_counter() - start
|
||||
|
||||
find_time = measure_find(ht_find, buckets, data)
|
||||
delete_time = measure_delete(ht_delete, buckets, data)
|
||||
|
||||
return insert_time, find_time, delete_time
|
||||
|
||||
|
||||
def test_bst(data):
|
||||
root = None
|
||||
|
||||
start = time.perf_counter()
|
||||
for name, phone in data:
|
||||
root = bst_insert(root, name, phone)
|
||||
insert_time = time.perf_counter() - start
|
||||
|
||||
find_time = measure_find(bst_find, root, data)
|
||||
delete_time = measure_delete(bst_delete, root, data)
|
||||
|
||||
return insert_time, find_time, delete_time
|
||||
|
||||
|
||||
def run():
|
||||
|
||||
results = []
|
||||
results.append(["Structure", "Order", "Insert", "Find", "Delete"])
|
||||
|
||||
for i in range(5):
|
||||
|
||||
shuffled, sorted_data = prepare_data()
|
||||
|
||||
# -------- LinkedList --------
|
||||
i1, f1, d1 = test_linked_list(shuffled)
|
||||
results.append(["LinkedList", "shuffled", i1, f1, d1])
|
||||
|
||||
i1, f1, d1 = test_linked_list(sorted_data)
|
||||
results.append(["LinkedList", "sorted", i1, f1, d1])
|
||||
|
||||
# -------- HashTable --------
|
||||
i2, f2, d2 = test_hash_table(shuffled)
|
||||
results.append(["HashTable", "shuffled", i2, f2, d2])
|
||||
|
||||
i2, f2, d2 = test_hash_table(sorted_data)
|
||||
results.append(["HashTable", "sorted", i2, f2, d2])
|
||||
|
||||
# -------- BST --------
|
||||
i3, f3, d3 = test_bst(shuffled)
|
||||
results.append(["BST", "shuffled", i3, f3, d3])
|
||||
|
||||
i3, f3, d3 = test_bst(sorted_data)
|
||||
results.append(["BST", "sorted", i3, f3, d3])
|
||||
|
||||
|
||||
|
||||
with open("results.csv", "w", newline="") as f:
|
||||
writer = csv.writer(f)
|
||||
writer.writerows(results)
|
||||
|
||||
print("Готово! results.csv создан")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
run()
|
||||
BIN
nehoroshevaa/docs/data_task1/delete.png
Normal file
BIN
nehoroshevaa/docs/data_task1/delete.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 127 KiB |
BIN
nehoroshevaa/docs/data_task1/find.png
Normal file
BIN
nehoroshevaa/docs/data_task1/find.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 121 KiB |
BIN
nehoroshevaa/docs/data_task1/insert.png
Normal file
BIN
nehoroshevaa/docs/data_task1/insert.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 89 KiB |
51
nehoroshevaa/docs/data_task1/plot.py
Normal file
51
nehoroshevaa/docs/data_task1/plot.py
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
|
||||
import csv
|
||||
import matplotlib.pyplot as plt
|
||||
from collections import defaultdict
|
||||
|
||||
|
||||
data = []
|
||||
|
||||
with open("results.csv", "r") as f:
|
||||
reader = csv.reader(f)
|
||||
next(reader) # header
|
||||
for row in reader:
|
||||
structure, order, insert, find, delete = row
|
||||
data.append((structure, order, float(insert), float(find), float(delete)))
|
||||
|
||||
|
||||
def group(metric_index):
|
||||
result = defaultdict(list)
|
||||
for s, o, ins, f, d in data:
|
||||
key = (s, o)
|
||||
result[key].append([ins, f, d][metric_index])
|
||||
return result
|
||||
|
||||
|
||||
def save_plot(metric_name, index, filename):
|
||||
|
||||
grouped = group(index)
|
||||
|
||||
plt.figure()
|
||||
|
||||
labels = []
|
||||
|
||||
for (structure, order), values in grouped.items():
|
||||
label = f"{structure}-{order}"
|
||||
labels.append(label)
|
||||
plt.plot(values, label=label)
|
||||
|
||||
plt.title(metric_name)
|
||||
plt.xlabel("Run")
|
||||
plt.ylabel("Time (sec)")
|
||||
plt.legend()
|
||||
|
||||
plt.savefig(filename, dpi=300, bbox_inches="tight")
|
||||
plt.close()
|
||||
|
||||
|
||||
save_plot("INSERT TIME", 0, "insert.png")
|
||||
save_plot("FIND TIME", 1, "find.png")
|
||||
save_plot("DELETE TIME", 2, "delete.png")
|
||||
|
||||
print("Графики сохранены: insert.png, find.png, delete.png")
|
||||
31
nehoroshevaa/docs/data_task1/results.csv
Normal file
31
nehoroshevaa/docs/data_task1/results.csv
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
Structure,Order,Insert,Find,Delete
|
||||
LinkedList,shuffled,3.1266312,0.0240491,0.0153019
|
||||
LinkedList,sorted,2.1736874,0.0176649,0.0123909
|
||||
HashTable,shuffled,0.0102941,0.000103,5.22E-05
|
||||
HashTable,sorted,0.0093038,0.0001008,5.37E-05
|
||||
BST,shuffled,0.0154676,0.000154,9.03E-05
|
||||
BST,sorted,8.3014441,0.0768616,0.0345065
|
||||
LinkedList,shuffled,3.2182401,0.0256622,0.0177542
|
||||
LinkedList,sorted,2.2604362,0.0199027,0.0131383
|
||||
HashTable,shuffled,0.0110818,0.0001227,5.32E-05
|
||||
HashTable,sorted,0.0098066,0.0001021,5.52E-05
|
||||
BST,shuffled,0.0184675,0.0001531,9.83E-05
|
||||
BST,sorted,8.6233891,0.0829446,0.0509548
|
||||
LinkedList,shuffled,3.2111766,0.0260377,0.0221557
|
||||
LinkedList,sorted,2.6125727,0.0275846,0.0190955
|
||||
HashTable,shuffled,0.014219,0.0001666,0.0003187
|
||||
HashTable,sorted,0.0138165,0.0001425,7.94E-05
|
||||
BST,shuffled,0.0234246,0.0002257,0.0001382
|
||||
BST,sorted,8.9193103,0.0615153,0.0415436
|
||||
LinkedList,shuffled,3.4287802,0.0276346,0.0178373
|
||||
LinkedList,sorted,2.4205873,0.0211635,0.0157121
|
||||
HashTable,shuffled,0.0113899,0.0001118,5.63E-05
|
||||
HashTable,sorted,0.0116161,0.0001284,6.88E-05
|
||||
BST,shuffled,0.0221165,0.0001773,0.0001002
|
||||
BST,sorted,9.0077053,0.1054247,0.0477643
|
||||
LinkedList,shuffled,3.2640041,0.0345332,0.0232472
|
||||
LinkedList,sorted,2.827502,0.0201937,0.0141592
|
||||
HashTable,shuffled,0.0105407,0.0001501,8.18E-05
|
||||
HashTable,sorted,0.0102284,0.0001005,5.58E-05
|
||||
BST,shuffled,0.0166355,0.0001603,9.34E-05
|
||||
BST,sorted,8.2043019,0.0622669,0.0375809
|
||||
|
BIN
nehoroshevaa/docs/report_1.docx
Normal file
BIN
nehoroshevaa/docs/report_1.docx
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user