#реализация справочника на основе бинарного дерева поиска (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']