概述
树形数据结构中二叉树的遍历问题是一个重要的问题,关于二叉树的遍历很容易就会想到使用递归的方式对二叉树节点进行遍历,但是这种遍历方式会导致比较大的空间复杂度。我们知道递归其实也就是使用栈的一种迭代实现,如何逻辑清晰的将递归的遍历方式转换为迭代的遍历是本文探讨的重点。
二叉树的前序中序后序遍历的迭代遍历法:
- 判断哪些节点是需要暂存的
- 判断什么情况下当前节点可以遍历(例如后序遍历:只有所有右子树节点都已经遍历完后才可以遍历当前节点)
递归使用栈是用栈实现的,利用栈与递归的对应关系实现递归与迭代的转换
目录
- 前序遍历
- 中序遍历
- 后序遍历
前序遍历
迭代遍历
def preorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
if not root:
return []
stack = []
pointer = root
ans = []
while stack or pointer:
while pointer:
ans.append(pointer.val)
stack.append(pointer)
pointer = pointer.left
pointer = stack.pop()
# 此处pointer已经被遍历,不需要暂存,直接用pointer.right取代pointer避免重复遍历 -> 1
pointer = pointer.right
return ans
中序遍历
中序遍历(前序遍历类似)递归与迭代的转换关系
traverse(root.left) --> while root:stack.append(root)
root = root.left
visit(root.val) --> stack.pop()
traverse(root.right) --> root = root.right
后序遍历
后序遍历递归与迭代的转换关系
traverse(root.left) --> while root:stack.append(root)
root = root.left
traverse(root.right) --> root = stack.pop()
visit --> if root.right == None or pre_root.right == root:visit
后序迭代遍历
def postorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
stack = []
pointer = root
ans = []
pre = None
if not root:
return ans
while stack or pointer:
while pointer:
stack.append(pointer)
pointer = pointer.left
pointer = stack.pop()
# 判断右节点是否为空,如果不为空则判断是否已经遍历
if not pointer.right or pointer.right == pre:
ans.append(pointer.val)
# 保存前继节点
pre = pointer
# 表示右侧节点已经遍历完毕,避免重复遍历右子树 -> 2
pointer = None
else:
# 对比前序遍历的此处,由于后续遍历此处pointer还没有遍历则还需要添加到stack -> 1
stack.append(pointer)
pointer = pointer.right
return ans