Leetcode145|二叉树的后续遍历 非递归实现 用辅助栈or只用一个栈

后续遍历的非递归方法更加复杂要用到辅助栈

通过上一篇的先序遍历我们知道它是通过变换头节点,先压入右孩子再压入左孩子做到的头左右的打印顺序

那么后续的遍历是打印左右头,我们要做的是把头先攒住,打完左右孩子再打印头,不要像之前那样变换的头进栈又出栈,但是这样很麻烦的一点在于我不知道啥时候改打头,我不知道啥时候右孩子被打完了

但是我们用辅助栈就可以做到这一点,我们先调整先序的只有进栈的顺序,把先序的先压右孩子再压左孩子,改成先压左孩子再压右孩子,最终可以得到头右左的顺序 存入辅助栈,再倒出来就得到的是左右头的后续了

/**
 * 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> postorderTraversal(TreeNode root) {
        List<Integer> list=new ArrayList<>();
        Stack<TreeNode> stack=new Stack<TreeNode>();
         Stack<TreeNode> s=new Stack<TreeNode>();
         if(root==null){return list;}
        s.add(root);
        while(!s.isEmpty()){
            root=s.pop();
            stack.push(root);
            if(root.left!=null){
                s.add(root.left);
            }
            if(root.right!=null){
                s.add(root.right);
            }
       
            
        }
        while(!stack.isEmpty()){
            list.add(stack.pop().val);
        }
        return list;
    }
}

 

当然也有不用辅助栈的做法 !

我们之前不是说不知道啥时候右孩子到头吗?

那么后续的遍历是打印左右头,我们要做的是把头先攒住,打完左右孩子再打印头,不要像之前那样变换的头进栈又出栈,但是这样很麻烦的一点在于我不知道啥时候改打头,我不知道啥时候右孩子被打完了

 我们可以用c来记录栈顶元素,root用来跟踪刚弹出的节点

如果c是刚到的:1.c(栈顶元素)的左孩子不为null

                            2.root(刚弹出的节点)不是c(栈顶元素)的左孩子

                            3.root(刚弹出的节点)不是c(栈顶元素)的右孩子

即if语句对应的条件左树没有被处理的情况,把栈顶c的左孩子压栈

elseif即右树没有被处理的条件1.栈顶的右孩子不为空2.刚弹出的节点root不是栈顶元素c的右孩子

那么把栈顶右孩子压栈

其他情况栈顶元素出栈,root跟踪这个出来了的元素

比如

 这棵树按后序遍历结果是

[4,5,2,6,7,3,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> postorderTraversal(TreeNode root) {
        List<Integer> list=new ArrayList<>();
        if(root!=null){
            Stack<TreeNode> stack=new Stack<TreeNode>();
            stack.push(root);//压头入栈
            TreeNode c=null;
            while(!stack.isEmpty()){
                c=stack.peek();
                //左树没处理的逻辑,c如果是新到的
                if(c.left!=null&&root!=c.left&&root!=c.right){
                    stack.push(c.left);
                }else if(c.right!=null&&root!=c.right){//右树没被处理的情况
                    stack.push(c.right);
                }else{
                    list.add(stack.pop().val);
                    root=c;
                }
            }
        }return list;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值