分析二叉树的先序遍历,中序遍历,后序遍历

二叉树的三种经典遍历方式:先序遍历、中序遍历和后序遍历。
这三种遍历方式是理解二叉树操作的基础,也是很多算法问题的核心。

核心思想
这三种遍历方式的名称源于 访问根节点的时机:

先序:先访问根节点,然后左子树,最后右子树
中序:先访问左子树,然后根节点,最后右子树
后序:先访问左子树,然后右子树,最后根节点
先序,中序,后序说的是针对根节点的访问顺序。


让我们通过一个具体的例子来分析。考虑以下二叉树:
      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);
}

理解这三种遍历方式对于解决二叉树相关问题至关重要。它们不仅是算法基础,也是很多实际应用的底层原理。
通过掌握递归和迭代两种实现方式,可以更灵活地应对不同场景的需求。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值