二叉树的遍历是指按照某种顺序访问二叉树中的每个节点。常见的遍历方式有四种:前序遍历(Pre-order Traversal)、中序遍历(In-order Traversal)、后序遍历(Post-order Traversal)以及层序遍历(Level-order Traversal)。每种遍历方式根据访问根节点的时机不同而有所区别。
概述
前序遍历(Pre-order Traversal)
在前序遍历中,首先访问根节点,然后递归地以前序方式遍历左子树,最后递归地以前序方式遍历右子树。即访问顺序为:根 -> 左 -> 右。
- 算法步骤:
- 访问根节点。
- 对根节点的左子树进行前序遍历。
- 对根节点的右子树进行前序遍历。
中序遍历(In-order Traversal)
在中序遍历中,首先递归地中序遍历左子树,然后访问根节点,最后递归地中序遍历右子树。即访问顺序为:左 -> 根 -> 右。
- 算法步骤:
- 对根节点的左子树进行中序遍历。
- 访问根节点。
- 对根节点的右子树进行中序遍历。
对于二叉查找树(BST),中序遍历将返回按升序排列的节点值。
后序遍历(Post-order Traversal)
在后序遍历中,首先递归地以后序方式遍历左子树,然后递归地以后序方式遍历右子树,最后访问根节点。即访问顺序为:左 -> 右 -> 根。
- 算法步骤:
- 对根节点的左子树进行后序遍历。
- 对根节点的右子树进行后序遍历。
- 访问根节点。
层序遍历(Level-order Traversal)
层序遍历又称广度优先遍历(BFS, Breadth-first Search),是按照从上到下、从左到右的顺序逐层访问树中的所有节点。与前面三种遍历方法不同的是,它不是递归实现的,而是通常使用队列来辅助完成。
- 算法步骤:
- 创建一个队列并将根节点加入队列。
- 当队列非空时,重复以下操作:
- 出队并访问队首节点。
- 将访问节点的左孩子和右孩子依次入队(如果存在的话)。
每种遍历方式都有其特定的应用场景,例如,前序遍历常用于复制树,中序遍历用于二叉查找树的排序输出,后序遍历可用于删除或释放节点资源,而层序遍历则有助于找到最短路径等问题。
例子
示例二叉树
假设我们有以下二叉树:
1
/ \
2 3
/ \ \
4 5 6
- 根节点是
1
。 - 左子树的根是
2
,右子树的根是3
。 - 节点
2
的左孩子是4
,右孩子是5
。 - 节点
3
的右孩子是6
。
前序遍历
访问顺序:根 -> 左 -> 右
[1, 2, 4, 5, 3, 6]
代码实现:
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
def pre_order_traversal(root):
result = []
def traverse(node):
if not node:
return
result.append(node.val) # 访问根节点
traverse(node.left) # 遍历左子树
traverse(node.right) # 遍历右子树
traverse(root)
return result
# 构建二叉树
root = TreeNode(1)
root.left = TreeNode(2)
root.right = TreeNode(3)
root.left.left = TreeNode(4)
root.left.right = TreeNode(5)
root.right.right = TreeNode(6)
print(pre_order_traversal(root)) # 输出: [1, 2, 4, 5, 3, 6]
中序遍历
访问顺序:左 -> 根 -> 右
[4, 2, 5, 1, 3, 6]
代码实现:
def in_order_traversal(root):
result = []
def traverse(node):
if not node:
return
traverse(node.left) # 遍历左子树
result.append(node.val) # 访问根节点
traverse(node.right) # 遍历右子树
traverse(root)
return result
print(in_order_traversal(root)) # 输出: [4, 2, 5, 1, 3, 6]
后序遍历
访问顺序:左 -> 右 -> 根
[4, 5, 2, 6, 3, 1]
代码实现:
def post_order_traversal(root):
result = []
def traverse(node):
if not node:
return
traverse(node.left) # 遍历左子树
traverse(node.right) # 遍历右子树
result.append(node.val) # 访问根节点
traverse(root)
return result
print(post_order_traversal(root)) # 输出: [4, 5, 2, 6, 3, 1]
层序遍历
访问顺序:从上到下、从左到右逐层访问
[1, 2, 3, 4, 5, 6]
代码实现:
from collections import deque
def level_order_traversal(root):
if not root:
return []
result = []
queue = deque([root]) # 初始化队列,根节点入队
while queue:
node = queue.popleft() # 出队并访问当前节点
result.append(node.val)
if node.left: # 如果左孩子存在,入队
queue.append(node.left)
if node.right: # 如果右孩子存在,入队
queue.append(node.right)
return result
print(level_order_traversal(root)) # 输出: [1, 2, 3, 4, 5, 6]
总结
遍历方式 | 访问顺序 | 示例结果 |
---|---|---|
前序遍历 | 根 -> 左 -> 右 | [1, 2, 4, 5, 3, 6] |
中序遍历 | 左 -> 根 -> 右 | [4, 2, 5, 1, 3, 6] |
后序遍历 | 左 -> 右 -> 根 | [4, 5, 2, 6, 3, 1] |
层序遍历 | 按层从左到右 | [1, 2, 3, 4, 5, 6] |
不同遍历方式适用于不同的场景,例如:
- 前序遍历:用于复制树、序列化树。
- 中序遍历:用于二叉查找树的排序输出。
- 后序遍历:用于删除树或释放资源。
- 层序遍历:用于寻找最短路径或按层级处理节点。