深度优选遍历有三种形式,先序遍历、中序、后序遍历。我们一般是用递归写的,因为好写也好理解。但偏偏在面试的时候,面试官可能要我们写迭代的写法。先序遍历的迭代写法很好写。但是另外两种就没那种容易一下就写出来的。
参考了leetcode解法,这里总结一下。
统一的框架
先序遍历
class Solution:
def preorderTraversal(self, root: TreeNode) -> List[int]:
stack = []
if not root:
return []
stack.append(root)
res = []
while stack:
p = stack.pop()
if p:
if p.right: # 先加入右子节点
stack.append(p.right)
if p.left: # 再加入左子节点
stack.append(p.left)
stack.append(p) # 再次加入当前节点
stack.append(None) # 用None代表stack之前的一个位置是已经访问过了
else: # 找到了一个访问过的位置
res.append(stack.pop().val)
return res
因为用栈,先序遍历要求先走根节点,再走左节点。后压入左子节点,为的是下次迭代先pop出的是左子节点。
大家也许会觉得None没有意义。但实际上,为了统一框架,None还是有意义的。当我们在写中序遍历和后序遍历的时候,None的作用就是很大的了。
中序遍历
仅仅更改注释的地方
class Solution:
def preorderTraversal(self, root: TreeNode) -> List[int]:
stack = []
if not root:
return []
stack.append(root)
res = []
while stack:
p = stack.pop()
if p:
if p.right:
stack.append(p.right)
stack.append(p) # 再次在加完右子节点之后,加入当前节点
stack.append(None) # 加入访问的标志
if p.left:
stack.append(p.left)
else:
res.append(stack.pop().val)
return res
后序遍历
class Solution:
def preorderTraversal(self, root: TreeNode) -> List[int]:
stack = []
if not root:
return []
stack.append(root)
res = []
while stack:
p = stack.pop()
if p:
stack.append(p) # 先加入访问过的节点
stack.append(None) # 加入访问的标志
if p.right:
stack.append(p.right)
if p.left:
stack.append(p.left)
else:
res.append(stack.pop().val)
return res