二叉树的前中后序遍历(递归+非递归)

首先来讲一下前中后序遍历的概念

不讲那么官方,其实就我个人的理解以及看大佬的视频和帖子,“前中后”这个概念就是针对根节点的;然后牢记一句废话“左边永远在右边的左边,右边永远在左边的右边”,就可以完美玩转前中后序这种基础的二叉树遍历,举个栗子~

前序:根->左->右 -----------> 根节点在前,左在左,右在右
中序:左->根->右 ------------> 根节点在中间,左在左,右在右
后序:左->右->根 ------------->根节点在后面,左在左,右在右

下面具体到代码实现

要遍历二叉树,我们先定义一个二叉树的类

class Node{
    Node left;
    Node right;
    int val;
    Node(){
        this.val=0;
    }
    Node(int val){
        this.val=val;
    }
}

以下所有代码都是基于以上的类属性来写的
先从前序遍历的递归开始,以下是我最先写的代码

前序遍历:

public class PreOrderTrevase {
    //前序遍历递归
   public void PreOrder(Node root){
       if(root==null){
           return;
       }
       System.out.println(root);
       PreOrder(root.left);
       PreOrder(root.right);
   }

后来又在leetcode上看到同一道题,但是返回值是个List,也就是不输出,按照前序遍历全部都放进一个list里面

public List<Integer> PreOrderByList(Node root){
       if(root==null){
         return list;
       }
       list.add(root.val);
       PreOrder(root.left);
       PreOrder(root.right);
       return list;
    }

但是对于很多盆友来说递归太简单,于是HR也是这么想的,所以很多公司其实都不问递归问的是非递归思想及代码
在这里需要用到栈,先将根节点放入栈,然后出栈,假设他有左右节点,栈的特性是后入先出,所以应该先放右子树再放左子树,然后出左树最后出右树

List<Integer> list=new LinkedList<>();
       Stack<Node> stack=new Stack<>();
       Node cur=root;
       while(!stack.isEmpty()||cur!=null){
           if(cur!=null){      //将左子树全部压入栈
               list.add(cur.val);
               stack.push(cur);
               cur=cur.left;
           }else{
               cur=stack.pop();
               cur=cur.right;
           }
       }
       return list;

中序遍历:
递归

List<Integer> list=new LinkedList<>();
    public List<Integer> inOrder(Node root){
      if(root==null){
          return list;
      }
      inOrder(root.left);
      list.add(root.val);
      inOrder(root.right);
      return list;
    }

非递归

 public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> list=new LinkedList<>();
    Stack<TreeNode> stack=new Stack<>();
        TreeNode cur=root;
        while(cur!=null||!stack.isEmpty()){
            if(cur!=null){
                stack.push(cur);
                cur=cur.left;
            }else{
                cur=stack.pop();
                list.add(cur.val);
                cur=cur.right;
            }
        }
        return list;
    }

后序遍历:
递归

   List<Integer> list=new LinkedList<>();
    public List<Integer> postOrder(Node root){
        if(root==null){
            return list;
        }
        postOrder(root.left);
        postOrder(root.right);
        list.add(root.val);
        return list;
    }

非递归

 List<Integer> list = new ArrayList<>();
    public List<Integer> postorderTraversal(TreeNode root) {
       Stack<TreeNode> stack= new Stack<>();
        TreeNode cur=root;
        TreeNode pre = null;
        while(cur!=null||!stack.isEmpty()){
            while(cur!=null){
                stack.push(cur);
                cur=cur.left;
            }
            cur = stack.peek();
            if(cur.right == null || cur.right==pre) {
                list.add(cur.val);
                stack.pop();
                pre = cur;//代表cur已经打印
                cur = null;
            }else {
                cur = cur.right;
            }
        }
        return list;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值