forked from UNN/2026-rff_mp
Merge pull request '[1] data structures' (#248) from VildyaevAV/2026-rff_mp:VildyaevAV-task1 into develop
Reviewed-on: UNN/2026-rff_mp#248
This commit is contained in:
commit
c4be844d2c
0
VildyaevAV/docs/report.md
Normal file
0
VildyaevAV/docs/report.md
Normal file
19
VildyaevAV/results.csv
Normal file
19
VildyaevAV/results.csv
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
Structure,Mode,Operation,Time
|
||||||
|
LinkedList,random,insert,2.179811800000607
|
||||||
|
LinkedList,random,find,0.019349800000782125
|
||||||
|
LinkedList,random,delete,0.01508280000052764
|
||||||
|
LinkedList,sorted,insert,1.7312419000008958
|
||||||
|
LinkedList,sorted,find,0.01827670000056969
|
||||||
|
LinkedList,sorted,delete,0.01452439999775379
|
||||||
|
HashTable,random,insert,0.13504540000212728
|
||||||
|
HashTable,random,find,0.0014485000028798822
|
||||||
|
HashTable,random,delete,0.0010058999978355132
|
||||||
|
HashTable,sorted,insert,0.12148510000042734
|
||||||
|
HashTable,sorted,find,0.0012095999991288409
|
||||||
|
HashTable,sorted,delete,0.0008018999978958163
|
||||||
|
BST,random,insert,0.016409800002293196
|
||||||
|
BST,random,find,0.0001536999989184551
|
||||||
|
BST,random,delete,9.40000027185306e-05
|
||||||
|
BST,sorted,insert,15.077545899999677
|
||||||
|
BST,sorted,find,0.05779409999740892
|
||||||
|
BST,sorted,delete,0.03522280000106548
|
||||||
|
345
VildyaevAV/task1.py
Normal file
345
VildyaevAV/task1.py
Normal file
|
|
@ -0,0 +1,345 @@
|
||||||
|
import random
|
||||||
|
import time
|
||||||
|
import csv
|
||||||
|
import sys
|
||||||
|
sys.setrecursionlimit(30000)
|
||||||
|
|
||||||
|
|
||||||
|
# =========================
|
||||||
|
# LINKED LIST
|
||||||
|
# =========================
|
||||||
|
|
||||||
|
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 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):
|
||||||
|
result = []
|
||||||
|
|
||||||
|
current = head
|
||||||
|
|
||||||
|
while current:
|
||||||
|
result.append((current["name"], current["phone"]))
|
||||||
|
current = current["next"]
|
||||||
|
|
||||||
|
return sorted(result)
|
||||||
|
|
||||||
|
|
||||||
|
# =========================
|
||||||
|
# HASH TABLE
|
||||||
|
# =========================
|
||||||
|
|
||||||
|
TABLE_SIZE = 1000
|
||||||
|
|
||||||
|
|
||||||
|
def hash_func(name):
|
||||||
|
return sum(ord(c) for c in name) % TABLE_SIZE
|
||||||
|
|
||||||
|
|
||||||
|
def ht_insert(buckets, name, phone):
|
||||||
|
index = hash_func(name)
|
||||||
|
buckets[index] = ll_insert(buckets[index], name, phone)
|
||||||
|
|
||||||
|
|
||||||
|
def ht_find(buckets, name):
|
||||||
|
index = hash_func(name)
|
||||||
|
return ll_find(buckets[index], name)
|
||||||
|
|
||||||
|
|
||||||
|
def ht_delete(buckets, name):
|
||||||
|
index = hash_func(name)
|
||||||
|
buckets[index] = ll_delete(buckets[index], name)
|
||||||
|
|
||||||
|
|
||||||
|
def ht_list_all(buckets):
|
||||||
|
result = []
|
||||||
|
|
||||||
|
for bucket in buckets:
|
||||||
|
result.extend(ll_list_all(bucket))
|
||||||
|
|
||||||
|
return sorted(result)
|
||||||
|
|
||||||
|
|
||||||
|
# =========================
|
||||||
|
# BST
|
||||||
|
# =========================
|
||||||
|
|
||||||
|
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_min(node):
|
||||||
|
current = node
|
||||||
|
|
||||||
|
while 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"]
|
||||||
|
|
||||||
|
if root["right"] is None:
|
||||||
|
return root["left"]
|
||||||
|
|
||||||
|
temp = bst_min(root["right"])
|
||||||
|
|
||||||
|
root["name"] = temp["name"]
|
||||||
|
root["phone"] = temp["phone"]
|
||||||
|
|
||||||
|
root["right"] = bst_delete(root["right"], temp["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"])
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# =========================
|
||||||
|
# TEST DATA
|
||||||
|
# =========================
|
||||||
|
|
||||||
|
N = 10000
|
||||||
|
|
||||||
|
records = [
|
||||||
|
(f"User_{i:05d}", str(random.randint(100000, 999999)))
|
||||||
|
for i in range(N)
|
||||||
|
]
|
||||||
|
|
||||||
|
records_shuffled = records[:]
|
||||||
|
random.shuffle(records_shuffled)
|
||||||
|
|
||||||
|
records_sorted = sorted(records)
|
||||||
|
|
||||||
|
|
||||||
|
# =========================
|
||||||
|
# BENCHMARK
|
||||||
|
# =========================
|
||||||
|
|
||||||
|
results = [
|
||||||
|
["Structure", "Mode", "Operation", "Time"]
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def benchmark_linked_list(records_input, mode):
|
||||||
|
global results
|
||||||
|
|
||||||
|
head = None
|
||||||
|
|
||||||
|
start = time.perf_counter()
|
||||||
|
|
||||||
|
for name, phone in records_input:
|
||||||
|
head = ll_insert(head, name, phone)
|
||||||
|
|
||||||
|
end = time.perf_counter()
|
||||||
|
|
||||||
|
results.append(["LinkedList", mode, "insert", end - start])
|
||||||
|
|
||||||
|
sample = random.sample(records_input, 100)
|
||||||
|
|
||||||
|
start = time.perf_counter()
|
||||||
|
|
||||||
|
for name, _ in sample:
|
||||||
|
ll_find(head, name)
|
||||||
|
|
||||||
|
end = time.perf_counter()
|
||||||
|
|
||||||
|
results.append(["LinkedList", mode, "find", end - start])
|
||||||
|
|
||||||
|
start = time.perf_counter()
|
||||||
|
|
||||||
|
for name, _ in sample[:50]:
|
||||||
|
head = ll_delete(head, name)
|
||||||
|
|
||||||
|
end = time.perf_counter()
|
||||||
|
|
||||||
|
results.append(["LinkedList", mode, "delete", end - start])
|
||||||
|
|
||||||
|
|
||||||
|
def benchmark_hash_table(records_input, mode):
|
||||||
|
global results
|
||||||
|
|
||||||
|
buckets = [None] * TABLE_SIZE
|
||||||
|
|
||||||
|
start = time.perf_counter()
|
||||||
|
|
||||||
|
for name, phone in records_input:
|
||||||
|
ht_insert(buckets, name, phone)
|
||||||
|
|
||||||
|
end = time.perf_counter()
|
||||||
|
|
||||||
|
results.append(["HashTable", mode, "insert", end - start])
|
||||||
|
|
||||||
|
sample = random.sample(records_input, 100)
|
||||||
|
|
||||||
|
start = time.perf_counter()
|
||||||
|
|
||||||
|
for name, _ in sample:
|
||||||
|
ht_find(buckets, name)
|
||||||
|
|
||||||
|
end = time.perf_counter()
|
||||||
|
|
||||||
|
results.append(["HashTable", mode, "find", end - start])
|
||||||
|
|
||||||
|
start = time.perf_counter()
|
||||||
|
|
||||||
|
for name, _ in sample[:50]:
|
||||||
|
ht_delete(buckets, name)
|
||||||
|
|
||||||
|
end = time.perf_counter()
|
||||||
|
|
||||||
|
results.append(["HashTable", mode, "delete", end - start])
|
||||||
|
|
||||||
|
|
||||||
|
def benchmark_bst(records_input, mode):
|
||||||
|
global results
|
||||||
|
|
||||||
|
root = None
|
||||||
|
|
||||||
|
start = time.perf_counter()
|
||||||
|
|
||||||
|
for name, phone in records_input:
|
||||||
|
root = bst_insert(root, name, phone)
|
||||||
|
|
||||||
|
end = time.perf_counter()
|
||||||
|
|
||||||
|
results.append(["BST", mode, "insert", end - start])
|
||||||
|
|
||||||
|
sample = random.sample(records_input, 100)
|
||||||
|
|
||||||
|
start = time.perf_counter()
|
||||||
|
|
||||||
|
for name, _ in sample:
|
||||||
|
bst_find(root, name)
|
||||||
|
|
||||||
|
end = time.perf_counter()
|
||||||
|
|
||||||
|
results.append(["BST", mode, "find", end - start])
|
||||||
|
|
||||||
|
start = time.perf_counter()
|
||||||
|
|
||||||
|
for name, _ in sample[:50]:
|
||||||
|
root = bst_delete(root, name)
|
||||||
|
|
||||||
|
end = time.perf_counter()
|
||||||
|
|
||||||
|
results.append(["BST", mode, "delete", end - start])
|
||||||
|
|
||||||
|
|
||||||
|
# =========================
|
||||||
|
# RUN TESTS
|
||||||
|
# =========================
|
||||||
|
|
||||||
|
benchmark_linked_list(records_shuffled, "random")
|
||||||
|
benchmark_linked_list(records_sorted, "sorted")
|
||||||
|
|
||||||
|
benchmark_hash_table(records_shuffled, "random")
|
||||||
|
benchmark_hash_table(records_sorted, "sorted")
|
||||||
|
|
||||||
|
benchmark_bst(records_shuffled, "random")
|
||||||
|
benchmark_bst(records_sorted, "sorted")
|
||||||
|
|
||||||
|
|
||||||
|
# =========================
|
||||||
|
# SAVE CSV
|
||||||
|
# =========================
|
||||||
|
|
||||||
|
with open("results.csv", "w", newline="") as f:
|
||||||
|
writer = csv.writer(f)
|
||||||
|
writer.writerows(results)
|
||||||
|
|
||||||
|
print("Done! Results saved to results.csv")
|
||||||
Loading…
Reference in New Issue
Block a user