你的代码有很多陷阱,它返回none的主要原因是因为btToDll什么都不返回,也没有改变head的值,它仍然是None。
与其尝试修复您的代码,我更愿意一次性采用不同的方法。
基本上,我找到了一个获得结果的技巧:
- 下到最左边的节点,成为 HEAD。
- 检查是否可以从头部向上移动,然后向左移动。或上一右等。如果可以向左,则将当前节点设置为左下节点。这样做直到没有任何节点。在 DLL 列表中添加上一个节点
- 从 Previoys 计算当前节点、它的前一个节点和 Right 节点。
- 从二叉树返回,到达根节点 (10),重复相同的模式。
你会看到,基本上,如果在任何给定的子节点中,有一个左节点,那么你计算整个三角形,最重要的节点总是左边,成为当前节点。如果左节点不存在,则父节点成为当前节点,则需要检查父节点是否有右节点。
我准备了一些图片,形象化比解释要好得多。
取这棵二叉树:
第一步 |尽可能去最左边的节点
第二步 |计算第一个三角形
注意:如果右下节点(30)有左子节点,则不添加30,本例就是这样,而是进入下一步。
第 3 步 |转到Child的子节点的下一个Triangle步骤##
第 4 步 |现在上到根节点计算BT的左边
注意:看这个算法的完整路径,我又想像那么多小三角形是分开计算的。
源代码
注意:已经很长了,但我是即时完成的,可以改进。
class BinaryTree():
def __init__(self, data):
self.data = data
self.left = None
self.right = None
self.prev = None
self.visited = False
def create_tree(self, show_tree=False):
"""Creating the Tree with a Depth-First Search Algorithm"""
root = self # Set Current Node
stack = [root]
while True:
if not stack:
break
current = stack.pop() # Remove Current From Stack
if current.right:
current.right.prev = current
stack.append(current.right)
if current.left:
current.left.prev = current
stack.append(current.left)
if show_tree:
print(f'{current.data} --> ', end='')
def create_dll(root_head):
"""Algorithm to Conver Binary Tree to Doubly Linked List"""
doubly_linked_list = []
# --- Find DLL Head NOTE: Just need to go left from Binary Tree till hit NONE
head = None
current = root_head
while True:
if current.left:
current = current.left
else:
head = current
break
stack = [head]
visited = set()
def add_node(*args, add_dll=None):
"""Helper Function, Add Node to the Visited Set."""
for item in args:
visited.add(item)
if add_dll:
for node in add_dll:
doubly_linked_list.append(node)
# --- Crawls back up, following each Triangle Shape from left Vertices to Right
while True:
try:
current = stack.pop()
except IndexError:
pass
if current in doubly_linked_list:
break
if current.left and current.left not in visited: # NOTE: Goes Down to Next Triangle Shape
stack.append(current.left)
continue
elif current.prev: # NOTE: Goes Up one Node
add_node(add_dll=[current])
# --------------- Check if we can go to the left.
if current.prev.right.left and current.prev.right.left not in visited: # NOTE: Goes deeper
add_node(current.prev, current.prev.right, add_dll=[current.prev])
if current.prev.prev: # NOTE: Backtracking
stack.append(current.prev.prev)
stack.append(current.prev.right.left)
continue
# ------------- Here We Handle in case previous Node Has ONLY Right path
elif current.prev.right.right:
if current.prev.right.right.left: # If has Left Node we go deeper
stack.append(current.right.right.left)
continue
add_node(add_dll=[current.prev.right.right])
else:
add_node(current.prev, add_dll=[current.prev])
if current.prev.right: # DOES the Prev node have a Right node?
add_node(current.prev.right, add_dll=[current.prev.right])
if current.prev.prev and current.prev.prev not in visited: # NOTE: BackTrackin
stack.append(current.prev.prev)
# -------------- >N OTE: Here Handle The 'Root node' (i.e. 10), only option is to go to right
elif current.right:
add_node(current, add_dll=[current])
if current.right.left: # Going Deeper
stack.append(current.right.left)
continue
elif current.right.right:
if current.right.right.left:
stack.append(current.right.right.left)
continue
add_node(current.right, current.right.right, add_dll=[current.right, current.right.right])
else:
add_node(current.right, add_dll=[current.right])
return doubly_linked_list
def show_ddl(ddl):
"""Helper function, used to print the Doubly Linked List"""
for node in ddl:
print(f'{node.data} --> ', end='')
# ---------> Creating The Binary Tree >
root = BinaryTree(10)
root.left = BinaryTree(12)
root.right = BinaryTree(15)
root.left.left = BinaryTree(25)
root.left.right = BinaryTree(30)
root.left.right.left = BinaryTree(60)
root.left.right.right = BinaryTree(77)
root.right.right = BinaryTree(40)
root.right.left = BinaryTree(36)
root.right.left.left = BinaryTree(50)
root.right.left.right = BinaryTree(13)
print('\nBynary Tree:\n')
root.create_tree(show_tree=True)
print()
print('==='*15)
print()
# ---------> Creating The Doubly Linked List >
print('Doubly Linked List:\n')
dll = create_dll(root)
show_ddl(dll)
输出
Bynary Tree:
10 --> 12 --> 25 --> 30 --> 60 --> 77 --> 15 --> 36 --> 50 --> 13 --> 40 -->
=============================================
Doubly Linked List:
25 --> 12 --> 60 --> 30 --> 77 --> 10 --> 50 --> 36 --> 13 --> 15 --> 40 -->