灵感来源
-
保持更新,努力学习
-
python脚本学习
二叉树的后序遍历
解题思路
后序遍历是二叉树遍历的一种,顺序为:左子树 → 右子树 → 根节点。递归实现后序遍历非常直观,按照遍历顺序递归访问左右子树后访问根节点即可。而非递归实现通常需要借助栈结构模拟递归过程,关键在于如何确保右子树在根节点之前被访问。
递归解法代码
python
class Solution:
def postorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
res = []
def postorder(node):
if not node:
return
postorder(node.left)
postorder(node.right)
res.append(node.val)
postorder(root)
return res
迭代解法代码
python
class Solution:
def postorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
res = []
if not root:
return res
stack = []
prev = None # 记录前一个访问的节点
current = root
while stack or current:
# 遍历到最左子节点
while current:
stack.append(current)
current = current.left
current = stack.pop()
# 如果右子树为空或已访问过右子树
if not current.right or current.right == prev:
res.append(current.val)
prev = current
current = None # 避免再次遍历左子树
else:
# 右子树存在且未访问,将当前节点重新压栈
stack.append(current)
current = current.right
return res
逐行解释
递归解法
python
class Solution:
def postorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
# 存储遍历结果的列表
res = []
# 定义内部递归函数
def postorder(node):
# 递归终止条件:节点为空
if not node:
return
# 递归遍历左子树
postorder(node.left)
# 递归遍历右子树
postorder(node.right)
# 访问当前节点(将值加入结果列表)
res.append(node.val)
# 从根节点开始递归
postorder(root)
return res
迭代解法
python
class Solution:
def postorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
res = [] # 存储遍历结果
if not root: # 处理空树
return res
stack = [] # 辅助栈
prev = None # 记录前一个访问的节点,用于判断右子树是否已访问
current = root # 当前节点指针
while stack or current: # 栈非空或当前节点非空时循环
# 遍历到当前子树的最左节点,并将路径上的节点压入栈
while current:
stack.append(current)
current = current.left
# 弹出栈顶节点进行处理
current = stack.pop()
# 条件1:右子树为空,无需处理
# 条件2:右子树已被访问过(通过prev判断)
if not current.right or current.right == prev:
res.append(current.val) # 访问当前节点
prev = current # 更新prev为当前节点
current = None # 置空当前节点,避免重复处理左子树
else:
# 右子树存在且未被访问,将当前节点重新压栈
stack.append(current)
# 转向处理右子树
current = current.right
return res
关键点解释
-
递归解法:
- 递归函数
postorder
的执行顺序决定了遍历方式 - 先处理左右子树,最后处理根节点,天然满足后序遍历定义
- 递归函数
-
迭代解法:
- 使用
prev
指针解决后序遍历的关键问题:如何确定右子树已被访问 - 当
current.right == prev
时,表示右子树已完成遍历,可处理当前节点 - 通过栈的压入 / 弹出操作模拟递归调用栈的行为
- 使用