用java实现二叉树的后序遍历(递归和迭代)

目录

1.题目内容

2.用递归实现后序遍历

2.1解题思路

2.2代码

3.用迭代实现后序遍历

3.1解题思路

3.2代码


1.题目内容

给你一棵二叉树的根节点 root ,返回其节点值的 后序遍历 。

示例 1:

输入:root = [1,null,2,3]
输出:[3,2,1]

示例 2:

输入:root = []
输出:[]

示例 3:

输入:root = [1]
输出:[1]

2.用递归实现后序遍历

2.1解题思路

后序遍历:左右根

递归:一种调用自己的循环

先递归的遍历左子树,再递归的遍历右子树,最后输出根节点。此方法是将以root为根的二叉树进行后序遍历,将每一个节点套用此方法。

1.重复的子问题。

        先遍历左子树,再遍历右子树,再输出根节点。

2.终止条件    

if(root==null){
    return;
}

2.2代码

public void postOrder(TreeNode root){
        if(root==null){
            return;
        }
        postOrder(root.left);
        postOrder(root.right);
        System.out.print(root.val+" ");
    }

3.用迭代实现后序遍历

3.1解题思路

后序遍历:左右根

递归问题可以用栈来解决,将这个栈模拟出来就是迭代。引入一个cur引用,对于后序遍历的根节点来说,cur要经过此节点三次,才能打印根节点。

第一次:从根节点开始去向左子树

第二次:从左子树回来,经过根节点,去向右子树

第三次:从右子树回来,去到根节点

如何判断cur经过了根节点三次呢?

在这里引入一个标记位prev,描述上一个被完全访问的节点是谁(当cur从某一个根节点的右子树返回时,此时这个右子节点已经被完全访问,使prev=cur.right,此时可以输出根节点)

步骤:

1.初始化一个空栈,cur引用一直向左子树遍历,走到头。同时将当前节点入栈。

while(cur!=null){
    stack.push(cur);
    cur=cur.left;
}

2.当前栈顶元素无左右子树,为叶子节点(将D的左右子树都访问过后再返回到D为第三次经过D节点),弹出栈顶元素。即cur.right==null时,可以输出根节点值。

cur=stack.pop();
list.add(cur.val);

 3.此时栈顶元素为B,右子树不为空,所以弹出后需要再次将它入栈。再接着将B的右孩子E入栈,E的左孩子为空,右孩子不为空,所以将E出栈再入栈。E的右孩子H左右孩子都为空,,将H入栈之后输出。但是当cur返回到E时,E的右孩子依旧不为空,此时会陷入到E和H的循环中去,所以这里引入一个标记位prev,描述上一个被访问完毕的元素。当右孩子为标记位时,说明此元素被访问完毕,直接弹出。

//右子树为空或已经被标记(访问结束)
if(root.right==null || prev==cur.right){
    //输出根节点,此时可以加入标记位
    list.add(cur.val);
    prev=cur;
    //当前树访问结束,不用再压入栈中,将cur置空,此时cur从当前栈中取元素
    cur=null;
}else{
    //右子树不为空,访问右子树
    stack.push(cur);
    cur=cur.right;
}

4.此时让cur置空,使cur指向栈顶元素,否则cur会指向步骤1的内容,访问左孩子。cur置空后指向栈顶元素E,E的左孩子为空,右孩子为标记位,所以直接输出。

5.prev此时指向E,将cur置空,此时cur指向栈顶元素B,继续上述步骤。

3.2代码

public List<Integer>postorderTraversal(TreeNode root){
        //初始化一个整形动态数组
        List<Integer>list=new ArrayList<>();
        //base case
        if(root==null){
            return list;
        }
        //定义一个引用cur指向root,当前要访问的节点
        TreeNode cur=root;
        //上一个完全访问结束的节点
        TreeNode prev=null;
        //初始化一个空栈
        Deque<TreeNode>stack=new LinkedList<>();
        while(cur!=null || !stack.isEmpty()){
            //先一路向左
            while(cur!=null){
                stack.push(cur);
                cur=cur.left;
            }
            //此时左子树为空,出栈
            cur=stack.pop();
            if(cur.right==null || prev==cur.right){
                //此时右子树为空或者已经访问结束
                list.add((int)cur.val);
                //更新prev为当前已被打印的节点
                prev=cur;
                //将cur置空,下一次循环从栈顶取元素
                cur=null;
            }else{
                //继续访问右子树
                stack.push(cur);
                cur=cur.right;
            }
        }
        return list;
    }

  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值