2026-03-20 17:06:29 +00:00
|
|
|
"""
|
|
|
|
|
Двоичное дерево поиска
|
|
|
|
|
|
|
|
|
|
Узел — словарь:
|
|
|
|
|
{'name': 'Имя', 'phone': '123', 'left': None, 'right': None}.
|
|
|
|
|
"""
|
|
|
|
|
|
2026-03-21 21:39:01 +00:00
|
|
|
def bst_insert(root: dict|None, name: str, phone: str) -> dict:
|
|
|
|
|
"""Итеративно вставляет, возвращает новый корень (если корень меняется)."""
|
|
|
|
|
if root == None:
|
|
|
|
|
return {'name': name, 'phone': phone, 'left': None, 'right': None}
|
|
|
|
|
|
|
|
|
|
# '674' < '722' == True, lol
|
|
|
|
|
current = root
|
|
|
|
|
while True:
|
|
|
|
|
if current['name'] == name:
|
2026-03-22 21:07:17 +00:00
|
|
|
current['phone'] = phone
|
|
|
|
|
return root
|
|
|
|
|
elif name < current['name']:
|
2026-03-21 21:39:01 +00:00
|
|
|
if current['left'] == None:
|
|
|
|
|
current['left'] = bst_insert(None, name, phone)
|
|
|
|
|
return root
|
|
|
|
|
else:
|
|
|
|
|
current = current['left']
|
|
|
|
|
else:
|
|
|
|
|
if current['right'] == None:
|
|
|
|
|
current['right'] = bst_insert(None, name, phone)
|
|
|
|
|
return root
|
|
|
|
|
else:
|
|
|
|
|
current = current['right']
|
|
|
|
|
# Увы, это самый лаконичный вариант, который я придумал.
|
2026-03-20 17:06:29 +00:00
|
|
|
|
|
|
|
|
|
2026-03-21 21:39:01 +00:00
|
|
|
def bst_find(root: dict|None, name: str) -> str|None:
|
|
|
|
|
"""Поиск в ширину."""
|
2026-03-22 21:07:17 +00:00
|
|
|
node = find_node_to_delete(root, name)
|
|
|
|
|
if node != None:
|
|
|
|
|
return node['phone']
|
|
|
|
|
|
|
|
|
|
def find_node_to_delete(root: dict, name: str) -> dict|None:
|
|
|
|
|
"""Поиск в ширину."""
|
|
|
|
|
while root != None:
|
|
|
|
|
if root['name'] == name:
|
|
|
|
|
return root
|
|
|
|
|
elif name < root['name']:
|
|
|
|
|
root = root['left']
|
|
|
|
|
else:
|
|
|
|
|
root = root['right']
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
def find_minimal_child(root: dict) -> dict|None:
|
|
|
|
|
while root['left']:
|
|
|
|
|
root = root['left']
|
|
|
|
|
return root
|
|
|
|
|
|
|
|
|
|
def bst_delete(root: dict, name: str) -> None:
|
|
|
|
|
"""Удаляет узел и возвращает новый корень."""
|
|
|
|
|
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:
|
|
|
|
|
# Случай 1: нет детей или один ребенок
|
|
|
|
|
if root['left'] is None:
|
|
|
|
|
return root['right']
|
|
|
|
|
elif root['right'] is None:
|
|
|
|
|
return root['left']
|
|
|
|
|
|
|
|
|
|
# Случай 2: два ребенка
|
|
|
|
|
min_node = find_minimal_child(root['right'])
|
|
|
|
|
root['name'] = min_node['name']
|
|
|
|
|
root['phone'] = min_node['phone']
|
|
|
|
|
root['right'] = bst_delete(root['right'], min_node['name'])
|
|
|
|
|
|
|
|
|
|
return root
|
2026-03-21 21:39:01 +00:00
|
|
|
|
2026-03-20 17:06:29 +00:00
|
|
|
|
2026-03-21 21:39:01 +00:00
|
|
|
def bst_list_all(root: dict) -> list:
|
2026-03-20 17:06:29 +00:00
|
|
|
"""Центрированный обход.
|
2026-03-22 21:07:17 +00:00
|
|
|
Рекурсивно собирает записи в отсортированном порядке."""
|
|
|
|
|
|
|
|
|
|
if root is None:
|
|
|
|
|
return []
|
|
|
|
|
node_values = {"name": root['name'], "phone": root['phone']}
|
|
|
|
|
return bst_list_all(root['left']) + [node_values] + bst_list_all(root['right'])
|