在树的深度优先遍历中(包括前序、中序、后序遍历),递归方法最为直观易懂,但考虑到效率,我们通常不推荐使用递归。
栈迭代方法虽然提高了效率,但其嵌套循环却非常烧脑,不易理解,容易造成“一看就懂,一写就废”的窘况。而且对于不同的遍历顺序(前序、中序、后序),循环结构差异很大,更增加了记忆负担。
因此,我在这里介绍一种“颜色标记法”(瞎起的名字……),兼具栈迭代方法的高效,又像递归方法一样简洁易懂,更重要的是,这种方法对于前序、中序、后序遍历,能够写出完全一致的代码。
其核心思想如下:
使用颜色标记节点的状态,新节点为白色,已访问的节点为灰色。
如果遇到的节点为白色,则将其标记为灰色,然后将其右子节点、自身、左子节点依次入栈。
栈是一种 先进后出
的结构,出栈顺序为左,中,右
那么入栈顺序必须调整为倒序,也就是右,中,左
同理,如果是前序遍历,入栈顺序为 右,左,中
;后序遍历,入栈顺序中,右,左
如果遇到的节点为灰色,则将节点的值输出。
class Solution:
def inorderTraversal(self, root: TreeNode) -> List[int]:
WHITE, GRAY = 0, 1
res = []
stack = [(WHITE, root)]
while stack:
color, node = stack.pop()
if node is None: continue
if color == WHITE:
stack.append((WHITE, node.right))
stack.append((GRAY, node))
stack.append((WHITE, node.left))
else:
res.append(node.val)
return res
如要实现前序、后序遍历,只需要调整左右子节点的入栈顺序即可。
white
对应TreeNode
数据类型,gray
对应int
数据类型,所以不需要额外的颜色标记:
class Solution:
def inorderTraversal(self, root: TreeNode) -> List[int]:
if not root: return []
stack,result = [root],[]
while stack:
item = stack.pop()
if isinstance(item,TreeNode):
stack.append(item.right)
stack.append(item.val)
stack.append(item.left)
elif isinstance(item,int):
result.append(item)
return result