二叉树的三种经典遍历方式:先序遍历、中序遍历和后序遍历。
这三种遍历方式是理解二叉树操作的基础,也是很多算法问题的核心。
核心思想
这三种遍历方式的名称源于 访问根节点的时机:
先序:先访问根节点,然后左子树,最后右子树
中序:先访问左子树,然后根节点,最后右子树
后序:先访问左子树,然后右子树,最后根节点
先序,中序,后序说的是针对根节点的访问顺序。
让我们通过一个具体的例子来分析。考虑以下二叉树:
A
/ \
B C
/ \ \
D E F
1. 先序遍历 (Preorder Traversal)
顺序:根节点 → 左子树 → 右子树
遍历结果: A → B → D → E → C → F
递归实现:
public void preorder(TreeNode root) {
if (root == null) return;
System.out.print(root.val + " "); // 1. 访问根节点
preorder(root.left); // 2. 遍历左子树 #方法里面套自己属于迭代。
preorder(root.right); // 3. 遍历右子树
}
#迭代实现(使用栈):
public void preorderIterative(TreeNode root) {
if (root == null) return;
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
while (!stack.isEmpty()) {
TreeNode node = stack.pop();
System.out.print(node.val + " ");
// 注意:先右后左,这样出栈时就是先左后右
//先后后左入栈,出栈就是先左后右边。
if (node.right != null) stack.push(node.right);
if (node.left != null) stack.push(node.left);
}
}
#应用场景:
#复制二叉树结构
#获取前缀表达式(波兰表达式)
2. 中序遍历 (Inorder Traversal)
顺序:左子树 → 根节点 → 右子树
遍历结果: D → B → E → A → C → F
//递归实现:
public void inorder(TreeNode root) {
if (root == null) return;
inorder(root.left); // 1. 遍历左子树 #迭代。
System.out.print(root.val + " "); // 2. 访问根节点
inorder(root.right); // 3. 遍历右子树
}
//迭代实现:
public void inorderIterative(TreeNode root) {
Stack<TreeNode> stack = new Stack<>();
TreeNode curr = root;
//||逻辑或。
while (curr != null || !stack.isEmpty()) {
// 将当前节点的所有左子节点入栈
while (curr != null) {
stack.push(curr); //整个root入栈
curr = curr.left; //
}
curr = stack.pop();
System.out.print(curr.val + " ");
curr = curr.right; // 转向右子树
}
}
//应用场景:
#二叉搜索树的中序遍历会得到升序结果
#中缀表达式求值
3. 后序遍历 (Postorder Traversal)
顺序:左子树 → 右子树 → 根节点
遍历结果: D → E → B → F → C → A
//递归实现:
public void postorder(TreeNode root) {
if (root == null) return;
postorder(root.left); // 1. 遍历左子树
postorder(root.right); // 2. 遍历右子树
System.out.print(root.val + " "); // 3. 访问根节点
}
//迭代实现(使用两个栈):
public void postorderIterative(TreeNode root) {
if (root == null) return;
Stack<TreeNode> stack1 = new Stack<>();
Stack<TreeNode> stack2 = new Stack<>();
stack1.push(root);
while (!stack1.isEmpty()) {
TreeNode node = stack1.pop();
stack2.push(node);
if (node.left != null) stack1.push(node.left);
if (node.right != null) stack1.push(node.right);
}
while (!stack2.isEmpty()) {
System.out.print(stack2.pop().val + " ");
}
}
应用场景:
释放二叉树内存(必须先释放子节点再释放父节点)
计算目录大小(必须先计算子目录大小)
后缀表达式(逆波兰表达式)求值
三种遍历对比总结
特性 |先序遍历 |中序遍历 |后序遍历
访问顺序 |根→左→右 |左→根→右 |左→右→根
第一个元素 |根节点 |最左叶子节点 |最左叶子节点
最后一个元素 |最右叶子节点 |最右叶子节点 |根节点
BST结果 |无特定顺序 |升序排列 |无特定顺序
空间复杂度 |O(h) |O(h) |O(h)
时间复杂度 |O(n) |O(n) |O(n)
记忆技巧
「先序」:根节点先访问
「中序」:根节点在中间访问
「后序」:根节点最后访问
实际应用示例
// 使用遍历计算二叉树深度
public int maxDepth(TreeNode root) {
if (root == null) return 0;
return Math.max(maxDepth(root.left), maxDepth(root.right)) + 1;
}
// 使用遍历判断两棵树是否相同
public boolean isSameTree(TreeNode p, TreeNode q) {
if (p == null && q == null) return true;
if (p == null || q == null) return false;
if (p.val != q.val) return false;
return isSameTree(p.left, q.left) && isSameTree(p.right, q.right);
}
理解这三种遍历方式对于解决二叉树相关问题至关重要。它们不仅是算法基础,也是很多实际应用的底层原理。
通过掌握递归和迭代两种实现方式,可以更灵活地应对不同场景的需求。
分析二叉树的先序遍历,中序遍历,后序遍历
最新推荐文章于 2025-12-15 08:57:28 发布
36万+

被折叠的 条评论
为什么被折叠?



