代码随想录算法训练营day14|二叉树

本文介绍了二叉树的前序、中序和后序遍历,提供了递归和迭代两种方法的Java代码实现。在迭代遍历中,重点解析了如何通过模拟栈操作来实现遍历,特别是对于前序、中序和后序的不同处理策略。对于中序和后序遍历,文章提出了使用null标记来解决节点状态判断的问题。
  • 递归遍历
    二叉树的遍历分为前序、中序、和后序,前中后代表双亲节点的位置。
    简单基础题
    class Solution {
        public List<Integer> preorderTraversal(TreeNode root) {
            List<Integer> result = new ArrayList<Integer>();
            preorder(root, result);
            return result;
        }
    
        public void preorder(TreeNode root, List<Integer> result) {
            if (root == null) {
                return;
            }
            result.add(root.val);
            preorder(root.left, result);
            preorder(root.right, result);
        }
    }

    有一定的基础了,因此只给出前序遍历的代码。

  • 迭代遍历
    迭代遍历就是不利用递归用循环结构来实现对二叉树的遍历。

    递归的底层逻辑是利用了栈的后进先出的结构来实现对二叉树的遍历,因此迭代遍历需要模拟递归运行的底层逻辑来进行。
    以前序遍历为例,在递归遍历中,显然根节点是最先被压入栈中,然后是先弹出根节点,然后输出根节点的值,同时再将根的左右结点分别压入栈中,因为左节点需要先出栈,因此进栈顺序应该为右左,按照这一个逻辑循环当每个结点展开后以及每个结点都被弹出输出,最后栈会被清空,因此循环的结束条件就是栈为空的时候。
  • 统一迭代
    由于前序遍历的特殊性,在每个双亲结点被弹出展开之后,只需要将左右子节点重新压入栈中,双亲结点可以直接进行输出不再重新压入栈中。
    但是,中序和后续遍历就无法这样,因为双亲结点并不是最先输出的,它需要按照输出的顺序重新被压入栈中保证遍历顺序的正确性。但是,在循环的过程中,遇到同一个结点时,我们无法确定这个结点此时应该进行展开还是进行弹出。
    所以,我决定在展开后的双亲结点重新入栈的时候,在它入栈前先压入一个null表示null的下一个结点已经经过展开,此时为输出状态。经过这样的处理,前中后的迭代遍历写法,只需要将代码的顺序进行移动就可以实现遍历顺序的转换。
    class Solution {
        public List<Integer> postorderTraversal(TreeNode root) {
            Stack<TreeNode> stack=new Stack<TreeNode>();
            List<Integer> res=new ArrayList<Integer>();
            if(root!=null) stack.push(root);
            while(!stack.isEmpty()){
                TreeNode cur=stack.pop();
                if(cur!=null){
                    
                    stack.push(cur);
                    stack.push(null);
                    if(cur.right!=null)stack.push(cur.right);
                    if(cur.left!=null)stack.push(cur.left);
                }else{
                    res.add(stack.pop().val);
    
                }
            }
            return res;
        }
    }

    以上是以后序遍历为例子,我在一开始思考迭代遍历时已经在往统一迭代的方向靠,因此在看了carl视频后结合自己的思考第一次写出的就是统一迭代代码。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值