我能够在不使用递归的情况下理解先序遍历,但我很难理解中序遍历。我似乎只是不明白,也许是因为我还没有理解递归的内部工作原理。
到目前为止,这是我尝试过的:
def traverseInorder(node):
lifo = Lifo()
lifo.push(node)
while True:
if node is None:
break
if node.left is not None:
lifo.push(node.left)
node = node.left
continue
prev = node
while True:
if node is None:
break
print node.value
prev = node
node = lifo.pop()
node = prev
if node.right is not None:
lifo.push(node.right)
node = node.right
else:
break
内部的 while 循环感觉不对。此外,一些元素被打印了两次;也许我可以通过检查之前是否打印过该节点来解决这个问题,但这需要另一个变量,这又一次感觉不对。我哪里错了?
我没有尝试过后序遍历,但我想它很相似,我也会在那里面临同样的概念障碍。
谢谢你的时间!
PS: Lifo
和 Node
的定义:
class Node:
def __init__(self, value, left=None, right=None):
self.value = value
self.left = left
self.right = right
class Lifo:
def __init__(self):
self.lifo = ()
def push(self, data):
self.lifo = (data, self.lifo)
def pop(self):
if len(self.lifo) == 0:
return None
ret, self.lifo = self.lifo
return ret
原文由 Srikanth 发布,翻译遵循 CC BY-SA 4.0 许可协议
从递归算法(伪代码)开始:
这是尾递归的一个明显例子,所以你可以很容易地将它变成一个 while 循环。
你剩下一个递归调用。递归调用所做的是将一个新的上下文压入堆栈,从头开始运行代码,然后检索上下文并继续执行它正在执行的操作。因此,您创建一个用于存储的堆栈和一个循环,该循环在每次迭代中确定我们是处于“首次运行”情况(非空节点)还是“返回”情况(空节点,非空堆栈) 并运行适当的代码:
难以掌握的是“返回”部分:你必须在循环中确定你正在运行的代码是处于“进入函数”状态还是处于“从调用返回”状态,并且你将有一个
if/else
链,其中包含与代码中的非终端递归一样多的情况。在这种特定情况下,我们使用节点来保存有关情况的信息。另一种方法是将其存储在堆栈本身中(就像计算机进行递归一样)。使用该技术,代码不是最优的,但更容易遵循