LeetCode-Py 项目:二叉树遍历算法详解
引言
二叉树是计算机科学中最基础也是最重要的数据结构之一,在算法面试和实际开发中都有着广泛应用。本文将深入讲解二叉树的四种基本遍历方式:前序遍历、中序遍历、后序遍历和层序遍历,帮助读者全面掌握二叉树遍历的核心思想与实现方法。
1. 二叉树遍历概述
二叉树遍历是指按照特定顺序访问树中所有节点的过程。根据访问顺序的不同,主要分为两大类遍历方式:
1.1 深度优先遍历 (DFS)
- 前序遍历:根节点 → 左子树 → 右子树
- 中序遍历:左子树 → 根节点 → 右子树
- 后序遍历:左子树 → 右子树 → 根节点
1.2 广度优先遍历 (BFS)
- 层序遍历:按层次从上到下,每层从左到右访问
理解这些遍历方式对于解决二叉树相关问题至关重要,比如:
- 前序遍历常用于复制二叉树
- 中序遍历常用于二叉搜索树的有序输出
- 后序遍历常用于计算表达式树
- 层序遍历常用于寻找最短路径或树的宽度
2. 前序遍历详解
2.1 递归实现
递归实现是最直观的方式,完全遵循前序遍历的定义:
def preorderTraversal(root):
res = []
def traverse(node):
if not node:
return
res.append(node.val) # 访问根节点
traverse(node.left) # 遍历左子树
traverse(node.right) # 遍历右子树
traverse(root)
return res
时间复杂度:O(n),每个节点访问一次 空间复杂度:O(h),h为树的高度,递归栈的深度
2.2 迭代实现
使用显式栈模拟递归过程:
def preorderTraversal(root):
if not root:
return []
res = []
stack = [root]
while stack:
node = stack.pop()
res.append(node.val)
if node.right: # 右子节点先入栈
stack.append(node.right)
if node.left: # 左子节点后入栈
stack.append(node.left)
return res
这种实现巧妙地利用了栈的LIFO特性,确保访问顺序为根→左→右。
3. 中序遍历详解
3.1 递归实现
def inorderTraversal(root):
res = []
def traverse(node):
if not node:
return
traverse(node.left) # 遍历左子树
res.append(node.val) # 访问根节点
traverse(node.right) # 遍历右子树
traverse(root)
return res
3.2 迭代实现
中序遍历的迭代实现较为复杂,需要维护当前节点指针:
def inorderTraversal(root):
res = []
stack = []
curr = root
while curr or stack:
while curr: # 深入左子树
stack.append(curr)
curr = curr.left
curr = stack.pop()
res.append(curr.val) # 访问节点
curr = curr.right # 转向右子树
return res
关键点在于:先将所有左子节点压栈,然后弹出访问,再处理右子树。
4. 后序遍历详解
4.1 递归实现
def postorderTraversal(root):
res = []
def traverse(node):
if not node:
return
traverse(node.left) # 遍历左子树
traverse(node.right) # 遍历右子树
res.append(node.val) # 访问根节点
traverse(root)
return res
4.2 迭代实现
后序遍历的迭代实现最为复杂,需要记录前一个访问的节点:
def postorderTraversal(root):
res = []
stack = []
prev = None
while root or stack:
while root:
stack.append(root)
root = root.left
root = stack.pop()
if not root.right or root.right == prev:
res.append(root.val)
prev = root
root = None
else:
stack.append(root)
root = root.right
return res
这种实现确保在访问节点前,其左右子树都已被访问。
5. 层序遍历详解
层序遍历使用队列实现广度优先搜索:
def levelOrder(root):
if not root:
return []
res = []
queue = [root]
while queue:
level_size = len(queue)
level = []
for _ in range(level_size):
node = queue.pop(0)
level.append(node.val)
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
res.append(level)
return res
关键点在于:
- 使用队列先进先出的特性
- 记录每层的节点数,确保分层存储结果
- 时间复杂度O(n),空间复杂度O(n)
6. 遍历方式对比与应用
| 遍历方式 | 访问顺序 | 典型应用场景 | |---------|---------|-------------| | 前序 | 根→左→右 | 复制二叉树,序列化 | | 中序 | 左→根→右 | 二叉搜索树有序输出 | | 后序 | 左→右→根 | 表达式求值,释放内存 | | 层序 | 按层访问 | 寻找最短路径,计算树宽 |
7. 总结
掌握二叉树的四种基本遍历方式是算法学习的基础。本文详细介绍了:
- 每种遍历方式的递归和迭代实现
- 各种实现的时间空间复杂度分析
- 不同遍历方式的应用场景
建议读者通过实际编码练习来巩固这些知识,理解不同遍历方式的本质区别。对于更复杂的二叉树问题,往往需要结合多种遍历方式来解决。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考