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 |