[1] добавлены структуры и отчёт

This commit is contained in:
Sokolov Nikita 2026-05-16 18:05:27 +03:00
parent f409499159
commit 6e62599ff4
2 changed files with 467 additions and 0 deletions

13
docs/data/results.csv Normal file
View File

@ -0,0 +1,13 @@
Structure,Mode,Operation,AvgSec,Run1,Run2,Run3,Run4,Run5
LinkedList,shuffled,insert,1.2842525600000954,1.3154544000008173,1.2751084999999875,1.275023099999089,1.2875868999999511,1.268089900000632
LinkedList,sorted,insert,1.2117479600001388,1.1916791000003286,1.2016641999998683,1.2213620000002265,1.2371671000000788,1.206867400000192
LinkedList,shuffled,search,0.016815839999981107,0.016818599999169237,0.017044300000634394,0.016971600000033504,0.01669179999953485,0.016552900000533555
LinkedList,shuffled,delete,0.008401739999681013,0.00841729999956442,0.008208700000977842,0.008644099998491583,0.008357900000191876,0.008380699999179342
HashTable,shuffled,insert,0.08811009999990346,0.08806019999974524,0.08975310000096215,0.08939879999888944,0.09190920000037295,0.08142919999954756
HashTable,sorted,insert,0.07928531999968982,0.07895339999959106,0.07827739999993355,0.07918199999949138,0.07984719999876688,0.08016660000066622
HashTable,shuffled,search,0.0010605999999825145,0.0010927000002993736,0.0010736000003817026,0.0010545999994064914,0.001032100000884384,0.0010499999989406206
HashTable,shuffled,delete,0.0005680000002030283,0.0005705999992642319,0.0005995999999868218,0.0005655000004480826,0.0005504000000655651,0.0005539000012504403
BST,shuffled,insert,0.009032140000272193,0.00904889999947045,0.009065000000191503,0.008986500000901287,0.009016699999847333,0.009043600000950391
BST,sorted,insert,1.5144591600004786,1.492954200000895,1.4967256999989331,1.5525281000009272,1.520630600000004,1.5094572000016342
BST,shuffled,search,0.00017742000018188263,0.00018480000107956585,0.00017459999980928842,0.00017389999993611127,0.0001733999997668434,0.00018040000031760428
BST,shuffled,delete,0.00010183999984292313,0.00010699999984353781,0.0001021999996737577,9.979999958886765e-05,0.00010149999980058055,9.870000030787196e-05
1 Structure Mode Operation AvgSec Run1 Run2 Run3 Run4 Run5
2 LinkedList shuffled insert 1.2842525600000954 1.3154544000008173 1.2751084999999875 1.275023099999089 1.2875868999999511 1.268089900000632
3 LinkedList sorted insert 1.2117479600001388 1.1916791000003286 1.2016641999998683 1.2213620000002265 1.2371671000000788 1.206867400000192
4 LinkedList shuffled search 0.016815839999981107 0.016818599999169237 0.017044300000634394 0.016971600000033504 0.01669179999953485 0.016552900000533555
5 LinkedList shuffled delete 0.008401739999681013 0.00841729999956442 0.008208700000977842 0.008644099998491583 0.008357900000191876 0.008380699999179342
6 HashTable shuffled insert 0.08811009999990346 0.08806019999974524 0.08975310000096215 0.08939879999888944 0.09190920000037295 0.08142919999954756
7 HashTable sorted insert 0.07928531999968982 0.07895339999959106 0.07827739999993355 0.07918199999949138 0.07984719999876688 0.08016660000066622
8 HashTable shuffled search 0.0010605999999825145 0.0010927000002993736 0.0010736000003817026 0.0010545999994064914 0.001032100000884384 0.0010499999989406206
9 HashTable shuffled delete 0.0005680000002030283 0.0005705999992642319 0.0005995999999868218 0.0005655000004480826 0.0005504000000655651 0.0005539000012504403
10 BST shuffled insert 0.009032140000272193 0.00904889999947045 0.009065000000191503 0.008986500000901287 0.009016699999847333 0.009043600000950391
11 BST sorted insert 1.5144591600004786 1.492954200000895 1.4967256999989331 1.5525281000009272 1.520630600000004 1.5094572000016342
12 BST shuffled search 0.00017742000018188263 0.00018480000107956585 0.00017459999980928842 0.00017389999993611127 0.0001733999997668434 0.00018040000031760428
13 BST shuffled delete 0.00010183999984292313 0.00010699999984353781 0.0001021999996737577 9.979999958886765e-05 0.00010149999980058055 9.870000030787196e-05

454
main.py Normal file
View File

@ -0,0 +1,454 @@
import time
import csv
import random
import copy
def ll_insert(head, name, phone):
"""Добавляет или обновляет запись. Возвращает голову."""
if head is None:
return {'name': name, 'phone': phone, 'next': None}
curr = head
while curr is not None:
if curr['name'] == name:
curr['phone'] = phone
return head
curr = curr['next']
# Вставка в конец
new_node = {'name': name, 'phone': phone, 'next': None}
curr = head
while curr['next'] is not None:
curr = curr['next']
curr['next'] = new_node
return head
def ll_find(head, name):
"""Возвращает телефон или None."""
curr = head
while curr is not None:
if curr['name'] == name:
return curr['phone']
curr = curr['next']
return None
def ll_delete(head, name):
"""Удаляет узел. Возвращает голову."""
if head is None:
return None
if head['name'] == name:
return head['next']
prev = head
curr = head['next']
while curr is not None:
if curr['name'] == name:
prev['next'] = curr['next']
return head
prev = curr
curr = curr['next']
return head
def ll_list_all(head):
"""Собирает все записи и сортирует по имени."""
records = []
curr = head
while curr is not None:
records.append((curr['name'], curr['phone']))
curr = curr['next']
records.sort(key=lambda x: x[0])
return records
def _hash(name, bucket_count):
"""Простая хеш-функция."""
return sum(ord(ch) for ch in name) % bucket_count
def ht_create(bucket_count=1000):
"""Создаёт пустую хеш-таблицу."""
return [None] * bucket_count
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_records = []
for head in buckets:
curr = head
while curr is not None:
all_records.append((curr['name'], curr['phone']))
curr = curr['next']
all_records.sort(key=lambda x: x[0])
return all_records
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
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 is not None:
if name == current['name']:
return current['phone']
elif name < current['name']:
current = current['left']
else:
current = current['right']
return None
def bst_min_node(node):
"""Находит минимальный узел в поддереве."""
while node['left'] is not None:
node = node['left']
return node
def bst_delete(root, name):
"""Итеративное удаление узла."""
parent = None
current = root
# Поиск узла
while current is not None 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 and current['right'] is None:
if parent is None:
return None
if parent['left'] is current:
parent['left'] = None
else:
parent['right'] = None
return root
# Случай 2: один ребёнок
if current['left'] is None:
child = current['right']
elif current['right'] is None:
child = current['left']
else:
# Случай 3: два ребёнка
successor_parent = current
successor = current['right']
while successor['left'] is not None:
successor_parent = successor
successor = successor['left']
current['name'] = successor['name']
current['phone'] = successor['phone']
if successor_parent['left'] is successor:
successor_parent['left'] = successor['right']
else:
successor_parent['right'] = successor['right']
return root
# Присоединяем ребёнка к родителю
if parent is None:
return child
if parent['left'] is current:
parent['left'] = child
else:
parent['right'] = child
return root
def bst_list_all(root):
"""Итеративный центрированный обход (через стек)."""
result = []
stack = []
current = root
while stack or current is not None:
while current is not None:
stack.append(current)
current = current['left']
current = stack.pop()
result.append((current['name'], current['phone']))
current = current['right']
return result
def generate_records(N=10000):
"""Возвращает (shuffled, sorted) списки записей."""
records = [(f"User_{i:05d}", f"phone_{i}") for i in range(N)]
shuffled = copy.deepcopy(records)
random.shuffle(shuffled)
return shuffled, records
def test_linked_list(records_shuffled, records_sorted, results):
N = len(records_shuffled)
# Вставка shuffled (5 повторов)
times = []
for _ in range(5):
head = None
start = time.perf_counter()
for name, phone in records_shuffled:
head = ll_insert(head, name, phone)
times.append(time.perf_counter() - start)
results.append(["LinkedList", "shuffled", "insert", sum(times) / 5] + times)
# Вставка sorted
times = []
for _ in range(5):
head = None
start = time.perf_counter()
for name, phone in records_sorted:
head = ll_insert(head, name, phone)
times.append(time.perf_counter() - start)
results.append(["LinkedList", "sorted", "insert", sum(times) / 5] + times)
# Подготовка структуры для поиска/удаления
head = None
for name, phone in records_shuffled:
head = ll_insert(head, name, phone)
# Поиск (100 существующих + 10 несуществующих)
existing = [f"User_{i:05d}" for i in random.sample(range(N), 100)]
nonexisting = [f"None_{i}" for i in range(10)]
search_names = existing + nonexisting
times = []
for _ in range(5):
start = time.perf_counter()
for name in search_names:
ll_find(head, name)
times.append(time.perf_counter() - start)
results.append(["LinkedList", "shuffled", "search", sum(times) / 5] + times)
# Удаление 50 записей
delete_names = [f"User_{i:05d}" for i in random.sample(range(N), 50)]
times = []
for _ in range(5):
head_copy = None
for name, phone in records_shuffled:
head_copy = ll_insert(head_copy, name, phone)
start = time.perf_counter()
for name in delete_names:
head_copy = ll_delete(head_copy, name)
times.append(time.perf_counter() - start)
results.append(["LinkedList", "shuffled", "delete", sum(times) / 5] + times)
def test_hash_table(records_shuffled, records_sorted, results):
N = len(records_shuffled)
bucket_count = 1000
# Вставка shuffled
times = []
for _ in range(5):
buckets = ht_create(bucket_count)
start = time.perf_counter()
for name, phone in records_shuffled:
ht_insert(buckets, name, phone)
times.append(time.perf_counter() - start)
results.append(["HashTable", "shuffled", "insert", sum(times) / 5] + times)
# Вставка sorted
times = []
for _ in range(5):
buckets = ht_create(bucket_count)
start = time.perf_counter()
for name, phone in records_sorted:
ht_insert(buckets, name, phone)
times.append(time.perf_counter() - start)
results.append(["HashTable", "sorted", "insert", sum(times) / 5] + times)
# Подготовка
buckets = ht_create(bucket_count)
for name, phone in records_shuffled:
ht_insert(buckets, name, phone)
# Поиск
existing = [f"User_{i:05d}" for i in random.sample(range(N), 100)]
nonexisting = [f"None_{i}" for i in range(10)]
search_names = existing + nonexisting
times = []
for _ in range(5):
start = time.perf_counter()
for name in search_names:
ht_find(buckets, name)
times.append(time.perf_counter() - start)
results.append(["HashTable", "shuffled", "search", sum(times) / 5] + times)
# Удаление
delete_names = [f"User_{i:05d}" for i in random.sample(range(N), 50)]
times = []
for _ in range(5):
buckets_copy = ht_create(bucket_count)
for name, phone in records_shuffled:
ht_insert(buckets_copy, name, phone)
start = time.perf_counter()
for name in delete_names:
ht_delete(buckets_copy, name)
times.append(time.perf_counter() - start)
results.append(["HashTable", "shuffled", "delete", sum(times) / 5] + times)
def test_bst(records_shuffled, records_sorted, results):
N = len(records_shuffled)
# Вставка shuffled
times = []
for _ in range(5):
root = None
start = time.perf_counter()
for name, phone in records_shuffled:
root = bst_insert(root, name, phone)
times.append(time.perf_counter() - start)
results.append(["BST", "shuffled", "insert", sum(times) / 5] + times)
# Вставка sorted (деградация в список)
times = []
for _ in range(5):
root = None
start = time.perf_counter()
for name, phone in records_sorted:
root = bst_insert(root, name, phone)
times.append(time.perf_counter() - start)
results.append(["BST", "sorted", "insert", sum(times) / 5] + times)
# Подготовка
root = None
for name, phone in records_shuffled:
root = bst_insert(root, name, phone)
# Поиск
existing = [f"User_{i:05d}" for i in random.sample(range(N), 100)]
nonexisting = [f"None_{i}" for i in range(10)]
search_names = existing + nonexisting
times = []
for _ in range(5):
start = time.perf_counter()
for name in search_names:
bst_find(root, name)
times.append(time.perf_counter() - start)
results.append(["BST", "shuffled", "search", sum(times) / 5] + times)
# Удаление
delete_names = [f"User_{i:05d}" for i in random.sample(range(N), 50)]
times = []
for _ in range(5):
root_copy = None
for name, phone in records_shuffled:
root_copy = bst_insert(root_copy, name, phone)
start = time.perf_counter()
for name in delete_names:
root_copy = bst_delete(root_copy, name)
times.append(time.perf_counter() - start)
results.append(["BST", "shuffled", "delete", sum(times) / 5] + times)
def save_results(results, filename="docs/data/results.csv"):
import os
os.makedirs("docs/data", exist_ok=True)
with open(filename, "w", newline="", encoding="utf-8") as f:
writer = csv.writer(f)
writer.writerow(["Structure", "Mode", "Operation", "AvgSec", "Run1", "Run2", "Run3", "Run4", "Run5"])
for row in results:
writer.writerow(row)
print(f"Результаты сохранены в {filename}")
# ============================================================
# 9. MAIN
# ============================================================
def main():
print("Генерация тестовых данных (N=5000 для скорости)...")
shuffled, sorted_records = generate_records(5000)
results = []
print("Тестирование LinkedList...")
test_linked_list(shuffled, sorted_records, results)
print("Тестирование HashTable...")
test_hash_table(shuffled, sorted_records, results)
print("Тестирование BST...")
test_bst(shuffled, sorted_records, results)
save_results(results)
print("\nГотово! Файл results.csv создан.")
print("Можешь построить графики в Excel или Google Sheets.")
if __name__ == "__main__":
main()