Чтобы преобразовать двоичное дерево в двусвязный список (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