【非递归】二叉树迭代遍历

模板

二叉树的遍历顺序还是如图,使用迭代就是增加一个栈,来储存父节点。利用读取的顺序来实现遍历顺序。

在这里插入图片描述
万能模板:

 while (root!=null||!stack.isEmpty()){
            while(root!=null){
                
            }
            if(!stack.isEmpty()){
                
            }
        }


一般是元素入栈,左子树迭代完,从栈中取出父节点,进行右子树迭代。

前序遍历

class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> res =new ArrayList<>();
        Stack<TreeNode> stack =new Stack<>();
        while (root!=null||!stack.isEmpty()){
            while(root!=null){
                stack.push(root);
                res.add(root.val);
                root=root.left;
            }
            if(!stack.isEmpty()){
                root=stack.pop();               
                root=root.right;
            }
        }
        return res;
    }
}

中序遍历

class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> res =new ArrayList<>();
        Stack<TreeNode> stack =new Stack<>();
        while (root!=null||!stack.isEmpty()){
            while(root!=null){
                stack.push(root);
                root=root.left;
            }
            if(!stack.isEmpty()){
                root=stack.pop();
                res.add(root.val);
                root=root.right;
            }
        }
        return res;
    }
}

后序遍历

//  后续:先遍历左节点
// 需要判断父节点是否有右节点或者右节点都访问过了,才可以输出父节点
// 父节点放在栈顶,定义一个参数p来记录最后访问的节点
class Solution {
    public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<>();
        if(root==null){
            return res;
        }
        Stack<TreeNode> stack =new Stack<>();
        TreeNode p =null; 
        while (root!=null||!stack.isEmpty()){
            while(root!=null){
                stack.push(root);
                root=root.left;
            }
            root= stack.pop();
            if(root.right==null||root.right==p){
                res.add(root.val);
                p=root;
                root=null;
                
            }
            else{
                root=root.right;
            }
        }
        return res;
    }
}

这里还有一个小的点:
在这里插入图片描述
为什么会出现这个问题是因为while左树遍历完之后,用if判断父节点右节点为空或者右节点已经遍历之后,应该把root赋值为null让他不进左树遍历的while循环,要不然就会超出时限。而且重复了。

评论区一个大佬思路:
前序遍历和中序遍历的模板,在什么时候返回 值的差别,而后序遍历需要多一个判断父节点的右孩子是否走完的过程。利用评论中一个大佬的思想:前序是每次把节点放入链表的最后,顺序是:根左右,那如果每次把节点放入链表最前就是:右左根,然后调换一下左右顺序就是实现了后续:左右根。
没有增加额外的判别过程。

按照大佬思路复现了一下发现出现问题,因为自己习惯用ArrayList,而ArrayList是有序的,实现头插入非常麻烦,所有的都应该后移。所以这时候,使用无序的LinkedList就会非常方便,然后用 addFirst函数实现头插。

//  后续遍历
class Solution {
    public List<Integer> postorderTraversal(TreeNode root) {
        // List<Integer> res = new LinkedList<>();
        LinkedList<Integer> res = new LinkedList<>();
        Stack<TreeNode> stack =new Stack<>();
        while (root!=null||!stack.isEmpty()){
            while(root!=null){
                stack.push(root);
                res.addFirst(root.val);
                root=root.right;
            }
            if(!stack.isEmpty()){
                root=stack.pop();
                root=root.left;
            }
        }
        return res;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值