二叉树的前序、中序、后序以及层次遍历(递归与非递归实现)

二叉树遍历往往会使用到递归,往往递归的方法是容易实现的,如果是非递归实现一般都是可以用栈或者队列实现。
二叉树定义

//Definition for a binary tree node.
 public class TreeNode {
     int val;
     TreeNode left;
     TreeNode right;
     TreeNode(int x) { val = x; }
 }

前序中序后序三种遍历的三种思想:
前序:根-左-右
中序:左-根-右
后序:左-右-根
三种遍历的顺序不同在代码中的体现往往就是顺序的一些不同。
层次遍历一般就是从根节点开始按层依次,与广度优先搜索类似。

二叉树前序遍历

前序遍历顺序是根-左-右
递归实现

	List<Integer> list=new ArrayList<>();
    public List<Integer> preorderTraversal(TreeNode root) {
        if(root!=null){
        	//根-左-右
            result.add(root.val);
            preorderTraversal(root.left);
            preorderTraversal(root.right);
        }
        return result;
    }

非递归实现

public List<Integer> preorderTraversal(TreeNode root) {
        Stack<TreeNode> stack=new Stack<>();
        ArrayList<Integer> list=new ArrayList<>();
        while(!stack.isEmpty()||root!=null){
            //root不为空就添加到结果集并入栈,再指向左节点
            if(root!=null){
                list.add(root.val);
                stack.push(root);
                root=root.left;
            }else{//root为空就出栈,指向右节点
                TreeNode pop=stack.pop();
                root=pop.right;
            }
        }
        return list;
    }

二叉树中序遍历

中序遍历的顺序是左-根-右
递归实现

	List<Integer> list=new ArrayList<>();
    public List<Integer> preorderTraversal(TreeNode root) {
        if(root!=null){
        	//左-根-右
            preorderTraversal(root.left);
            list.add(root.val)
            preorderTraversal(root.right);
        }
        return result;
    }

非递归实现

public List<Integer> inorderTraversal(TreeNode root) {
        ArrayList<Integer> list = new ArrayList<>();
        Stack<TreeNode> stack = new Stack<>();
        while(root!=null||!stack.isEmpty()){
            while(root!=null){
                stack.push(root);//根结点先进后出
                root = root.left;//遍历左结点
            }
            root = stack.pop();//遍历到最左结点先出栈
            list.add(root.val);
            root = root.right;//遍历右节点
        }
        return list;
    }

二叉树后序遍历

后序遍历的顺序是左-根-右
递归实现

List<Integer> list=new ArrayList<>();
    public List<Integer> preorderTraversal(TreeNode root) {
        if(root!=null){
        	//左-右=根
            preorderTraversal(root.left);
            preorderTraversal(root.right);
            list.add(root.val)
        }
        return list;
    }

非递归实现
这里用到了链表,且链表采用头插法,这样就可以将先插入的根结点致于末尾,一般往往不同的打印顺序可以使用不同的插入方法实现。
PS:也可以直接使用动态数组,在加入数值时每次都从第一个位置加入,也可以满足链表的逆序。

public List<Integer> inorderTraversal(TreeNode root) {
        Stack<TreeNode> stack=new Stack<>();
        LinkedList<Integer> list=new LinkedList<>();
        if(root==null)
            return list;
        //从上到下,从左至右将节点入栈,依次出栈,得到的结果反向输出即可
        stack.add(root);
        while(!stack.isEmpty()){
            TreeNode pop=stack.pop();
            //总是将结果添加到头部,相当于反转了结果
            list.addFirst(pop.val);
            if(pop.left!=null)
                stack.push(pop.left);
            if(pop.right!=null)
                stack.push(pop.right);
        }
        return list;
}

二叉树层次遍历

二叉树层次遍历可以采用队列先进先出的思想实现,每次只让一层结点入队,并依次出队,同时将该结点的左右结点入队。
简单层次遍历(所有结点放入一个list)

public ArrayList<Integer> PrintFromTopToBottom(TreeNode root) {
	ArrayList<Integer> list=new ArrayList<>();
    Queue<TreeNode> queue=new LinkedList<>();
    if(root!=null) queue.add(root);
    while(!queue.isEmpty()){
    	TreeNode node=queue.poll();
    	list.add(node.val);
    	if(node.left!=null) queue.add(node.left);
    	if(node.right!=null) queue.add(node.right);
    }
    return list;
}

层次遍历(按层输出)
多一个队列元素计数标志(还有按之字形打印二叉树的面试题,也只是元素插入顺序不同而已)具体而已

public ArrayList<ArrayList<Integer> > PrintFromTopToBottom(TreeNode Root) {
        ArrayList<ArrayList<Integer>> res=new ArrayList<>();
        if(Root==null) return res;
        Queue<TreeNode> queue=new LinkedList<>();
        queue.add(Root);
        while(!queue.isEmpty()){
            int count=queue.size();
            ArrayList<Integer> list=new ArrayList<>();
            while(count>0){
                TreeNode node=queue.poll();
                list.add(node.val);
                if(node.left!=null) queue.add(node.left);
                if(node.right!=null) queue.add(node.right);
                count--;
            }
            res.add(list);
        }
        return res;
 }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值