2026-rff_mp/groshevava/docs/data/bst.py

153 lines
4.7 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.

#реализация справочника на основе бинарного дерева поиска (BST).
#создаём узел
def bst_create_node(name, phone):
return {
'name': name,
'phone': phone,
'left': None,
'right': None
}
#Вставляет запись в BST или обновляет.Возвращает корень дерева
def bst_insert(root, name, phone):
new_node = bst_create_node(name, phone)
if root is None:
return new_node
current = root
parent = None
while current is not None:
parent = current
if name < current['name']:
current = current['left']
elif name > current['name']:
current = current['right']
else:
current['phone'] = phone
return root
#вставляем новый узел
if name < parent['name']:
parent['left'] = new_node
else:
parent['right'] = new_node
return root
#ищет запись в BST по имени. Возвращает телефон или None
def bst_find(root, name):
current = root
while current is not None:
if name == current['name']:
return current['phone']
elif name < current['name']:
current = current['left']
else:
current = current['right']
return None
#Находит узел с минимальным значением
def _bst_find_min(node):
current = node
while current['left'] is not None:
current = current['left']
return current
#удаляет запись из BST по имени. Возвращает новый корень дерева
def bst_delete(root, name):
if root is None:
return None
parent = None
current = root
while current is not None and current['name'] != name:
parent = current
if name < current['name']:
current = current['left']
else:
current = current['right']
if current is None:
return root
if current['left'] is None and current['right'] is None:
if parent is None:
return None
elif parent['left'] == current:
parent['left'] = None
else:
parent['right'] = None
return root
if current['left'] is None:
if parent is None:
return current['right']
elif parent['left'] == current:
parent['left'] = current['right']
else:
parent['right'] = current['right']
return root
if current['right'] is None:
if parent is None:
return current['left']
elif parent['left'] == current:
parent['left'] = current['left']
else:
parent['right'] = current['left']
return root
successor_parent = current
successor = current['right']
while successor['left'] is not None:
successor_parent = successor
successor = successor['left']
current['name'] = successor['name']
current['phone'] = successor['phone']
if successor_parent == current:
successor_parent['right'] = successor['right']
else:
successor_parent['left'] = successor['right']
return root
#рекурсивно собирает записи дерева по возрастанию имён
def _bst_in_order_collect(node, records):
if node is not None:
_bst_in_order_collect(node['left'], records)
records.append((node['name'], node['phone']))
_bst_in_order_collect(node['right'], records)
#отсортированный список всех записей
def bst_list_all(root):
records = []
# Для очень глубоких деревьев лучше использовать итеративный обход
_bst_in_order_iterative(root, records)
return records
#центрированный обход дерева.
def _bst_in_order_iterative(root, records):
stack = []
current = root
while current is not None or len(stack) > 0:
# доходим до самого левого узла
while current is not None:
stack.append(current)
current = current['left']
# обрабатываем узел
current = stack.pop()
records.append((current['name'], current['phone']))
#переходим к правому поддереву
current = current['right']