153 lines
4.6 KiB
Python
153 lines
4.6 KiB
Python
|
|
import csv
|
|||
|
|
import random
|
|||
|
|
import sys
|
|||
|
|
import time
|
|||
|
|
import threading
|
|||
|
|
|
|||
|
|
|
|||
|
|
sys.setrecursionlimit(30000)
|
|||
|
|
threading.stack_size(64*1024*1024)
|
|||
|
|
|
|||
|
|
|
|||
|
|
def ll_insert(head, name, phone):
|
|||
|
|
"""Добавляет запись или обновляет телефон, если имя уже существует. Возвращает новую голову списка."""
|
|||
|
|
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": head}
|
|||
|
|
return new_node
|
|||
|
|
|
|||
|
|
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):
|
|||
|
|
"""Удаляет узел по имени. Возвращает новую голову списка."""
|
|||
|
|
curr = head
|
|||
|
|
prev = None
|
|||
|
|
|
|||
|
|
while curr is not None:
|
|||
|
|
if curr["name"] == name:
|
|||
|
|
if prev is None:
|
|||
|
|
return curr["next"]
|
|||
|
|
else:
|
|||
|
|
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 ht_create(size=1000):
|
|||
|
|
"""Создает пустую хеш-таблицу заданного размера."""
|
|||
|
|
return [None] * size
|
|||
|
|
|
|||
|
|
def ht_insert(buckets, name, phone):
|
|||
|
|
"""Вычисляет индекс бакета и вызывает ll_insert."""
|
|||
|
|
idx = abs(hash(name)) % len(buckets)
|
|||
|
|
buckets[idx] = ll_insert(buckets[idx], name, phone)
|
|||
|
|
|
|||
|
|
def ht_find(buckets, name):
|
|||
|
|
"""Вычисляет индекс бакета и вызывает ll_find."""
|
|||
|
|
idx = abs(hash(name)) % len(buckets)
|
|||
|
|
return ll_find(buckets[idx], name)
|
|||
|
|
|
|||
|
|
def ht_delete(buckets, name):
|
|||
|
|
"""Вычисляет индекс бакета и вызывает ll_delete."""
|
|||
|
|
idx = abs(hash(name)) % len(buckets)
|
|||
|
|
buckets[idx] = ll_delete(buckets[idx], name)
|
|||
|
|
|
|||
|
|
def ht_list_all(buckets):
|
|||
|
|
"""Собирает записи из всех бакетов и сортирует их по имени."""
|
|||
|
|
records = []
|
|||
|
|
for head in buckets:
|
|||
|
|
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 bst_insert(root, name, phone):
|
|||
|
|
"""Рекурсивно вставляет узел или обновляет телефон."""
|
|||
|
|
if root is None:
|
|||
|
|
return {"name": name, "phone": phone, "left": None, "right": None}
|
|||
|
|
|
|||
|
|
if name == root["name"]:
|
|||
|
|
root["phone"] = phone
|
|||
|
|
elif name < root["name"]:
|
|||
|
|
root["left"] = bst_insert(root["left"], name, phone)
|
|||
|
|
else:
|
|||
|
|
root["right"] = bst_insert(root["right"], name, phone)
|
|||
|
|
|
|||
|
|
return root
|
|||
|
|
|
|||
|
|
def bst_find(root, name):
|
|||
|
|
"""Рекурсивный поиск по дереву."""
|
|||
|
|
if root is None:
|
|||
|
|
return None
|
|||
|
|
|
|||
|
|
if name == root["name"]:
|
|||
|
|
return root["phone"]
|
|||
|
|
elif name < root["name"]:
|
|||
|
|
return bst_find(root["left"], name)
|
|||
|
|
else:
|
|||
|
|
return bst_find(root["right"], name)
|
|||
|
|
|
|||
|
|
def bst_delete(root, name):
|
|||
|
|
"""Рекурсивное удаление узла из BST."""
|
|||
|
|
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):
|
|||
|
|
"""Центрированный обход дерева для сбора записей."""
|
|||
|
|
records = []
|
|||
|
|
def _inorder(node):
|
|||
|
|
if node is not None:
|
|||
|
|
_inorder(node["left"])
|
|||
|
|
records.append((node["name"], node["phone"]))
|
|||
|
|
_inorder(node["right"])
|
|||
|
|
|
|||
|
|
_inorder(root)
|
|||
|
|
return records
|