第六关|层次遍历

1、概述

 2、基本的层次遍历

如上图逻辑  [3, 9, 20, 15, 7]

public class SimpleLevelOrder {
    public static void main(String[] args) {

        BinaryTree bTree = new BinaryTree();
        bTree.root = bTree.buildBinaryTree();//建树

        List<Integer> level = simpleLevelOrder(bTree.root);
        System.out.println(level.toString());
        System.out.println(level);

    }
    
    public static List<Integer> simpleLevelOrder(TreeNode root){
        
        if(root == null){
            return new ArrayList<Integer>();
        }
        
        List<Integer> res = new ArrayList<>();
        LinkedList<TreeNode> queue = new LinkedList<>();

        //根节点放入队列,不断遍历
        queue.add(root);
        //size = 0时,即这一层完毕,该遍历下一层了
        while(queue.size() > 0){
            TreeNode t = queue.remove();
            res.add(t.val);

            //移出后,把它的左孩子和右孩子加入队列
            if(t.left != null){
                queue.add(t.left);
            }
            if(t.right != null){
                queue.add(t.right);
            }
        }

        return res;
    }
}
public class TreeNode {
    public int val;
    public TreeNode left;
    public TreeNode right;

    public TreeNode(int val){
        this.val = val;
    }

    public TreeNode(int val, TreeNode left, TreeNode right){
        this.val = val;
        this.left = left;
        this.right = right;
    }
}
public class BinaryTree {

    public TreeNode root;

    public BinaryTree() {
        root = null;
    }

    public TreeNode buildBinaryTree() {
        TreeNode node = new TreeNode(3);
        node.left = new TreeNode(9);
        node.right = new TreeNode(20);
        node.right.right = new TreeNode(7);
        node.right.left = new TreeNode(15);
        return node;
    }
}

3、层次遍历按层输出

用一个size记录层元素的个数,每一层size个元素出队后,刚好可以把该层作为list存储,下次for循环遍历下一层的元素。[[3],[9,20],[15,7]]

    public static List<List<Integer>> level102Order(TreeNode root){

        if(root == null){
            return new ArrayList<List<Integer>>();
        }

        List<List<Integer>> res = new ArrayList<List<Integer>>();
        LinkedList<TreeNode> queue = new LinkedList<>();

        queue.add(root);

        while(queue.size() > 0){

            //以层为单位
            int size = queue.size();
            ArrayList<Integer> tmp = new ArrayList<>();

            //以层出队列,并把它的子孩子加入队列
            for (int i = 0; i < size; i++) {
                TreeNode t = queue.remove();
                tmp.add(t.val);

                if(t.left != null){
                    queue.add(t.left);
                }
                if(t.right != null){
                    queue.add(t.right);
                }
            }

            res.add(tmp);

        }
        return res;
    }

4、自底向上层序遍历

与上面只是1个区别,待输出的最外层列表在添加层时从0处加,即res.add(0,tmp)

[[15,7],[9,20],[3]]

public class LevelOrderBottom {
    public static void main(String[] args) {

        BinaryTree bTree = new BinaryTree();
        bTree.root = bTree.buildBinaryTree();

        List<List<Integer>> level = levelOrderBottom(bTree.root);
        System.out.println(level);
    }

    public static List<List<Integer>> levelOrderBottom(TreeNode root){

        List<List<Integer>> res = new LinkedList<List<Integer>>();

        if(root == null){
            return res;
        }

        Queue<TreeNode> queue = new LinkedList<TreeNode>();
        queue.offer(root);

        while(!queue.isEmpty()){

            //以层为单位
            List<Integer> tmp = new LinkedList<>();//ArrayList<>和LinkedList<>都可以,定义头不是全写也可以
            int size = queue.size();

            for (int i = 0; i < size; i++) {
                TreeNode t = queue.poll();
                tmp.add(t.val);//不是queue,是add,没有offer

                if(t.left != null){
                    queue.offer(t.left);
                }

                if(t.right != null){
                    queue.offer(t.right);
                }
            }

            //入一层节点,因为是自底向上,所以从0入
            res.add(0,tmp);
        }
        return res;
    }
}

5、锯齿形层序遍历

奇数层:从左至右输出,偶数层:从右往左输出

如果从左至右,我们每次将被遍历到的元素插入至双端队列的末尾。

从右至左,我们每次将被遍历到的元素插入至双端队列的头部。

   public static List<List<Integer>> zigzagLevelOrder(TreeNode root){

        List<List<Integer>> res = new LinkedList<List<Integer>>();
        if(root == null){
            return res;
        }

        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        boolean isOrderLeft = true;//是否从左往右,1行,默认true

        while(!queue.isEmpty()){

            //以层为单位
            Deque<Integer> tmp = new LinkedList<>();
            int size = queue.size();

            for (int i = 0; i < size; i++) {

                TreeNode t = queue.poll();
                if(isOrderLeft == true){
                    tmp.offerLast(t.val);
                }else{
                    tmp.offerFirst(t.val);
                }
                if(t.left != null){
                    queue.offer(t.left);
                }
                if(t.right != null){
                    queue.offer(t.right);
                }

            }
            res.add(new LinkedList<Integer>(tmp));//定义头转换一下,不能是Deque
            isOrderLeft = !isOrderLeft;//别忘了,锯齿形。而且不能用-号时!号
        }
        return res;
    }

6、N叉树层序遍历

与前面差不多,只不过当节点出队列的时候不像之前:如果有,把它们的左右子孩子加入队列。而现在是一个集合,一个集合的孩子加入队列。

    public static List<List<Integer>> nLevelOrder(NTreeNode root){

        List<List<Integer>> res = new ArrayList<List<Integer>>();

        if(root == null){
            return res;
        }

        Queue<NTreeNode> queue = new LinkedList<>();
        queue.offer(root);

        while(!queue.isEmpty()){

            List<Integer> temp = new ArrayList<>();
            int size = queue.size();

            for (int i = 0; i < size; i++) {
                NTreeNode t = queue.poll();
                temp.add(t.val);

                for(NTreeNode node: t.children){
                    queue.offer(node);
                }

            }

            res.add(temp);
        }

        return res;
    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值