forked from UNN/2026-rff_mp
163 lines
4.5 KiB
Python
163 lines
4.5 KiB
Python
"""Телефонный справочник на трёх структурах данных."""
|
|
|
|
|
|
def _node(name, phone, next_node=None):
|
|
return {"name": name, "phone": phone, "next": next_node}
|
|
|
|
|
|
def ll_insert(head, name, phone):
|
|
"""Добавить запись в конец списка или обновить существующую."""
|
|
if head is None:
|
|
return _node(name, phone)
|
|
|
|
current = head
|
|
while True:
|
|
if current["name"] == name:
|
|
current["phone"] = phone
|
|
return head
|
|
if current["next"] is None:
|
|
current["next"] = _node(name, phone)
|
|
return head
|
|
current = current["next"]
|
|
|
|
|
|
def ll_find(head, name):
|
|
current = head
|
|
while current is not None:
|
|
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"]
|
|
|
|
previous, current = head, head["next"]
|
|
while current is not None:
|
|
if current["name"] == name:
|
|
previous["next"] = current["next"]
|
|
break
|
|
previous, current = current, current["next"]
|
|
return head
|
|
|
|
|
|
def ll_list_all(head):
|
|
records = []
|
|
current = head
|
|
while current is not None:
|
|
records.append((current["name"], current["phone"]))
|
|
current = current["next"]
|
|
return sorted(records, key=lambda record: record[0])
|
|
|
|
|
|
def _require_buckets(buckets):
|
|
if not buckets:
|
|
raise ValueError("Хеш-таблица должна содержать хотя бы один бакет")
|
|
|
|
|
|
def _hash_index(name, bucket_count):
|
|
"""Хеш-функция."""
|
|
value = 0
|
|
for character in name:
|
|
value = (value * 31 + ord(character)) % bucket_count
|
|
return value
|
|
|
|
|
|
def ht_insert(buckets, name, phone):
|
|
_require_buckets(buckets)
|
|
index = _hash_index(name, len(buckets))
|
|
buckets[index] = ll_insert(buckets[index], name, phone)
|
|
|
|
|
|
def ht_find(buckets, name):
|
|
_require_buckets(buckets)
|
|
return ll_find(buckets[_hash_index(name, len(buckets))], name)
|
|
|
|
|
|
def ht_delete(buckets, name):
|
|
_require_buckets(buckets)
|
|
index = _hash_index(name, len(buckets))
|
|
buckets[index] = ll_delete(buckets[index], name)
|
|
|
|
|
|
def ht_list_all(buckets):
|
|
_require_buckets(buckets)
|
|
records = []
|
|
for head in buckets:
|
|
records.extend(ll_list_all(head))
|
|
return sorted(records, key=lambda record: record[0])
|
|
|
|
|
|
def _bst_node(name, phone):
|
|
return {"name": name, "phone": phone, "left": None, "right": None}
|
|
|
|
|
|
def bst_insert(root, name, phone):
|
|
if root is None:
|
|
return _bst_node(name, phone)
|
|
|
|
current = root
|
|
while True:
|
|
if name == current["name"]:
|
|
current["phone"] = phone
|
|
return root
|
|
side = "left" if name < current["name"] else "right"
|
|
if current[side] is None:
|
|
current[side] = _bst_node(name, phone)
|
|
return root
|
|
current = current[side]
|
|
|
|
|
|
def bst_find(root, name):
|
|
current = root
|
|
while current is not None:
|
|
if name == current["name"]:
|
|
return current["phone"]
|
|
current = current["left"] if name < current["name"] else current["right"]
|
|
return None
|
|
|
|
|
|
def bst_delete(root, name):
|
|
parent = None
|
|
current = root
|
|
while current is not None and current["name"] != name:
|
|
parent = current
|
|
current = current["left"] if name < current["name"] else current["right"]
|
|
if current is None:
|
|
return root
|
|
|
|
if current["left"] is not None and current["right"] is not None:
|
|
successor_parent = current
|
|
successor = current["right"]
|
|
while successor["left"] is not None:
|
|
successor_parent = successor
|
|
successor = successor["left"]
|
|
current["name"], current["phone"] = successor["name"], successor["phone"]
|
|
parent, current = successor_parent, successor
|
|
|
|
child = current["left"] if current["left"] is not None else current["right"]
|
|
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):
|
|
records, stack = [], []
|
|
current = root
|
|
while stack or current is not None:
|
|
while current is not None:
|
|
stack.append(current)
|
|
current = current["left"]
|
|
current = stack.pop()
|
|
records.append((current["name"], current["phone"]))
|
|
current = current["right"]
|
|
return records
|