2026-rff_mp/MylnikovAS/task_1/data/ll_ht_bst.py

153 lines
4.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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