力扣题94二叉树的中序遍历

这篇博客介绍了三种不同的二叉树中序遍历方法:递归、迭代和Morris遍历。递归和迭代都是使用栈来辅助遍历,而Morris遍历则通过修改树结构达到O(1)的空间复杂度。每种方法都有详细的代码实现,并附有示例验证其正确性。
摘要由CSDN通过智能技术生成

给定一个二叉树的根节点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]

1.自己的解法。利用递归进行左---根---右的遍历,利用一个栈来存储中间遍历到的节点的值。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> list = new ArrayList<>();
        
        if(root == null){//如果树为空,直接返回即可
            return list;
        }
        
        Deque<Integer> stack = new LinkedList<>();//利用一个栈来存储中间遍历到的节点的值

        inorderMiddle(root,list,stack);

        return list;
    }

    public void inorderMiddle(TreeNode root,List<Integer> list,Deque<Integer> stack){
        stack.push(root.val);//将当前节点的值压入栈

        if(root.left != null){//如果有左子树,继续遍历左子树
            inorderMiddle(root.left,list,stack);
        }

        list.add(stack.peek());//左子树遍历完成后,将栈顶元素加入队列,并且栈顶元素出栈
        stack.pop();

        if(root.right != null){//如果有右子树,继续遍历右子树
            inorderMiddle(root.right,list,stack);
        }
    } 
}

2.迭代写法。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> list = new ArrayList<>();
        Deque<TreeNode> stack = new LinkedList<>();//利用一个栈来存储中间遍历到的节点

        while(root != null || !stack.isEmpty()){//节点不为空,或者栈不为空
            while(root != null){//左子树存在的话,就一直把左子节点压入栈
                stack.push(root);
                root = root.left;
            }
            //左子树不存在了
            root = stack.pop();//当前栈顶元素即为最后一个左子节点,并且将该节点出栈
            list.add(root.val);//将该节点的值加入list集合中

            root = root.right;//继续判断当前节点的右子树
        }

        return list;
    }
}

3.Morris中序遍历。能将非递归的中序遍历空间复杂度降为 O(1)。

   参考资料:Morris 遍历_微冷-CSDN博客_morris中序遍历 

class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> list = new ArrayList<Integer>();
        TreeNode prior = null;

        while(root != null){
            if(root.left != null){//左子树存在
                //找到在遍历顺序中当前节点的前一个结点,使前一个节点的右指针指向当前节点,这样之后可以从下层回到上层
                prior = root.left;
                while(prior.right != null && prior.right != root){//左子树最右边的节点是当前节点的前一个节点
                    prior = prior.right;
                }

                if(prior.right == null){//右子树不存在,说明第一次遍历到这一层
                    prior.right = root;
                    root = root.left;//继续向左遍历
                }else{//右子树存在,说明当前节点的左子树已经遍历完毕,回到了上层
                    list.add(root.val);//相当于把遍历完的左子树的根节点加入队列
                    prior.right = null;//断开之前自己创建的连接
                    root = root.right;//继续遍历当前根节点的右子树
                }
            }else{//左子树不存在,将根节点加入队列,继续遍历右子树
                list.add(root.val);
                root = root.right;
            }
        }
        return list;
    }
}

题源:力扣

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值