Преобразование двоичного дерева в двусвязный список (DLL): методы и примеры кода

Чтобы преобразовать двоичное дерево в двусвязный список (DLL), вы можете использовать несколько методов, таких как рекурсия, итеративный подход или обход Морриса. Ниже я объясню каждый метод и приведу примеры кода для лучшего понимания.

Метод 1: Рекурсия
В этом методе мы выполним обход двоичного дерева по порядку и изменим указатели для преобразования его в DLL.

class TreeNode:
    def __init__(self, val):
        self.val = val
        self.left = None
        self.right = None
def binary_tree_to_dll(root):
    if not root:
        return None

    def convert(node):
        nonlocal prev, head

        if not node:
            return

        convert(node.left)

        if prev:
            prev.right = node
            node.left = prev
        else:
            head = node

        prev = node

        convert(node.right)

    head = None
    prev = None
    convert(root)

    return head

Метод 2: итеративный подход (с использованием стека)
В этом методе мы будем использовать итеративный подход вместе со стеком для выполнения упорядоченного обхода двоичного дерева.

def binary_tree_to_dll(root):
    if not root:
        return None

    stack = []
    node = root
    prev = None
    head = None

    while stack or node:
        while node:
            stack.append(node)
            node = node.left

        node = stack.pop()

        if prev:
            prev.right = node
            node.left = prev
        else:
            head = node

        prev = node
        node = node.right

    return head

Метод 3: обход Морриса
Обход Морриса позволяет нам преобразовать двоичное дерево в DLL без использования дополнительного пространства. Он изменяет структуру дерева, передавая правильные указатели к следующему узлу в последовательности обхода.

def binary_tree_to_dll(root):
    if not root:
        return None

    def find_predecessor(node):
        while node.right and node.right != root:
            node = node.right
        return node

    curr = root
    prev = None
    head = None

    while curr:
        if not curr.left:
            if prev:
                prev.right = curr
                curr.left = prev
            else:
                head = curr
            prev = curr
            curr = curr.right
        else:
            predecessor = find_predecessor(curr.left)
            if not predecessor.right:
                predecessor.right = curr
                curr = curr.left
            else:
                predecessor.right = None
                if prev:
                    prev.right = curr
                    curr.left = prev
                else:
                    head = curr
                prev = curr
                curr = curr.right

    return head