二叉树的非递归遍历——易记版

在力扣上做题的时候发现了大佬给的二叉树非递归遍历的模板,前中后序只需要套用一个模板就行了,非常好记。原版本是C++写的,链接如下:

作者:sonp
链接:https://leetcode-cn.com/problems/binary-tree-postorder-traversal/solution/mo-fang-di-gui-zhi-bian-yi-xing-by-sonp/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

以下用java实现,其中的注释也与原版相同。

思路

需要一个标志区分每个递归调用栈,这里使用 nullptr 来表示。

Java代码

先序遍历

访问顺序为中、左、右,入栈顺序为右、左、中。

public List<Integer> preorderTraversal(TreeNode root) {
        ArrayList<Integer> output = new ArrayList<>();  //保存结果
        LinkedList<TreeNode> stack = new LinkedList<>();  //调用栈
        if(root == null) return output;  

        stack.add(root);  //首先入栈root节点
        TreeNode temp;
        while(!stack.isEmpty()){
            temp = stack.pollLast();  //访问过的节点弹出
            if(temp != null){
                if(temp.right != null) stack.add(temp.right);  //右节点先压栈,最后处理
                if(temp.left != null) stack.add(temp.left);
                stack.add(temp);  //当前节点重新压栈(留着以后处理),因为先序遍历所以最后压栈
                stack.add(null);  //在当前节点之前加入一个空节点表示已经访问过了
            }
            else{//空节点表示之前已经访问过了,现在需要处理除了递归之外的内容
                temp = stack.pollLast();  //temp是null之前压栈的一个节点,也就是上面stack.add(temp)中的那个temp
                output.add(temp.val);  //处理当前节点
            }
        }
        return output;
    }
中序遍历

访问顺序为左、中、右,入栈顺序为右、中、左。
只有注释的地方的顺序改了,哈哈是不是很好记,为大佬点赞。

public List<Integer> inorderTraversal(TreeNode root) {
        ArrayList<Integer> output = new ArrayList<>();
        LinkedList<TreeNode> stack = new LinkedList<>();
        if(root == null) return output;

        stack.add(root);
        TreeNode temp;
        while(!stack.isEmpty()){
            temp = stack.pollLast();
            if(temp != null){
                if(temp.right != null) stack.add(temp.right);
                stack.add(temp);  //在左节点之前重新插入该节点,以便在左节点之后处理(访问值)
                stack.add(null);  null跟随temp插入,标识已经访问过,还没有被处理
                if(temp.left != null) stack.add(temp.left);
            }
            else{
                temp = stack.pollLast();
                output.add(temp.val);
            }
        }
        return output;
    }
后序遍历

访问顺序为左、右、中,入栈顺序为中、左、右。

public List<Integer> postorderTraversal(TreeNode root) {
        ArrayList<Integer> output = new ArrayList<>();
        LinkedList<TreeNode> stack = new LinkedList<>();
        if(root == null) return output;

        stack.add(root);
        TreeNode temp;
        while(!stack.isEmpty()){
            temp = stack.pollLast();
            if(temp != null){
                stack.add(temp);  //在右节点之前重新插入该节点,以便在最后处理(访问值)
                stack.add(null);  //nullptr跟随t插入,标识已经访问过,还没有被处理
                if(temp.right != null) stack.add(temp.right);
                if(temp.left != null) stack.add(temp.left);
            }
            else{
                temp = stack.pollLast();
                output.add(temp.val);
            }
        }
        return output;
    }
对比中序遍历的递归写法
void dfs(t){ //进入函数表示“访问过”,将t从栈中弹出

    dfs(t->left);   //因为要访问t->left, 所以我先把函数中下面的信息都存到栈里。
                //依次call.push(t->right), call.push(t)【t第二次入栈】, call.push(nullptr)【标识t二次入栈】, call.push(t->left)。
                //此时t并没有被处理(卖萌)。栈顶是t->left, 所以现在进入t->left的递归中。

    //res.push_back(t->val)
    t.卖萌();   //t->left 处理完了,t->left被彻底弹出栈。
                //此时栈顶是nullptr, 表示t是已经访问过的。那么我现在需要真正的处理t了(即,执行卖萌操作)。
                //卖萌结束后,t 就被彻底弹出栈了。
    

    dfs(t->right); 
}


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值