2026-rff_mp/SmirnovVS/docs/data/1-st-exercize/phonebook.py
2026-09-04 17:34:55 +00:00

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