94-二叉树的中序遍历

这篇博客介绍了如何进行二叉树的中序遍历,包括递归、迭代和Morris中序遍历三种方法。递归方式是从根节点开始,左子树递归遍历,然后访问根节点,最后遍历右子树。迭代方式使用栈,先将根节点和左子树入栈,然后循环直到没有左节点,依次弹出节点并访问,最后遍历右节点。Morris遍历则通过修改二叉树结构,实现空间复杂度为O(1)的中序遍历。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目

给定一个二叉树的根节点 root ,返回它的 中序 遍历。

示例 1:

输入:root = [1,null,2,3]
输出:[1,3,2]

示例 2:

输入:root = []
输出:[]

示例 3:

输入:root = [1]
输出:[1]

示例 4:

输入:root = [1,2]
输出:[2,1]

示例 5:

输入:root = [1,null,2]
输出:[1,2]

题解一 递归

class Solution {
    List<Integer> res;
    public List<Integer> inorderTraversal(TreeNode root) {
        res=new ArrayList<>();
        if(root==null){
            return res;
        }
        inOrder(root);
        return res;
    }
    private void inOrder(TreeNode root){
        if(root==null){
            return;
        }
        inOrder(root.left);
        res.add(root.val);
        inOrder(root.right);
    }
}

//官方题解 中序遍历的时候用递归一般返回都是void,注意这点
class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<Integer>();
        inorder(root, res);
        return res;
    }

    public void inorder(TreeNode root, List<Integer> res) {
        if (root == null) {
            return;
        }
        inorder(root.left, res);
        res.add(root.val);
        inorder(root.right, res);
    }
}

题解二 迭代

public class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        // 栈 先进后出
        // 前序遍历,出栈顺序:根左右; 入栈顺序:右左根
        // 中序遍历,出栈顺序:左根右; 入栈顺序:右根左
        // 后序遍历,出栈顺序:左右根; 入栈顺序:根右左
        List<Integer> ans = new ArrayList<Integer>();
        Stack<TreeNode> stack = new Stack<>();
        // root为空且stack为空,遍历结束
        while (root != null || !stack.isEmpty()) {
            //注意是||,只要有一个满足条件即可!
            // 先根后左入栈
            
            //不断往左子树方向走,每走一次就将当前节点保存到栈中
			//这是模拟递归的调用
            while (root != null) {
                stack.push(root);//优先一直遍历左节点直到不能遍历为止!
                root = root.left;
                //当前节点为空,说明左边走到头了,从栈中弹出节点并保存
				//然后转向右边节点,继续上面整个过程             
            }
            // 此时root==null,说明上一步的root没有左子树
            // 1. 执行左出栈。因为此时root==null,导致root.right一定为null
            // 2. 执行下一次外层while代码块,根出栈。此时root.right可能存在
            // 3a. 若root.right存在,右入栈,再出栈
            // 3b. 若root.right不存在,重复步骤2
            root = stack.pop();//修改根!!!
            ans.add(root.val);//出栈时再记录!
            root = root.right;
        }
        return ans;
    }
}

笔记:

  1. 迭代的遍历用栈维护。先根节点入栈,然后左节点,最后右节点。先左边循环入,入到没有左为止,然后弹出,出值,指向右。

题解三 Morris 中序遍历

class Solution {
	public List<Integer> inorderTraversal(TreeNode root) {
		List<Integer> res = new ArrayList<Integer>();
		TreeNode pre = null;
		while(root!=null) {
			//如果左节点不为空,就将当前节点连带右子树全部挂到
			//左节点的最右子树下面
			if(root.left!=null) {
				pre = root.left;
				while(pre.right!=null) {//找到左节点的最右子树
					pre = pre.right;
				}
				pre.right = root;
				//将root指向root的left
				TreeNode tmp = root;
				root = root.left;
				tmp.left = null;//为什么不能直接置null?
			//左子树为空,则打印这个节点,并向右边遍历	
			} else {
				res.add(root.val);
				root = root.right;
			}
		}
		return res;
	}
}

笔记:

  1. 将非递归的中序遍历空间复杂度降为O(1)
  2. 将二叉树化解成一条链表,顺序遍历。

  3. 对于二叉树中的所有的节点, 1 如果它的左子树为空,那么也就是说该节点的前驱就是她自身。 2 如果它的左子树不空。那么利用文中的for语句来找到当前节点的前驱节点。如果找到之后,根据该前驱节点的右指针是否为空,来决定是加线索还是去掉线索。

  4. 看根节点是否有左子树,如果没有则直接打印该节点并向右遍历,若有的话找到左子树的最右节点pre,将根节点挂到pre上。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

codrab

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值