二叉树的层序遍历 + 通过层序遍历实现二叉树的操作

目录

一、二叉树的层序遍历

二、int sizeOf(TreeNode root) :获取树中结点个数

三、 int  leafSizeOf(TreeNode root) :获取叶子结点的个数

四、带层数的层序遍历

1. 使用打包的方式: class TreeNodeWithLevel 

2. 使用两个队列:nodeQueue 和 levelQueue

五、int getKLevelSize(TreeNode root , int k) :获取第 k 层结点的个数

六、int heightOf(TreeNode root) :获取二叉树的高度

七、boolean isCompleteTree(TreeNode root):判断一棵树是否是完全二叉树


一、二叉树的层序遍历

     凡是广度优先遍历,都要用到队列。使用队列确保先进先出(FIFO)。

     层序遍历要求从上往下(每个结点负责其孩子),从左往右(先左子树再右子树)。取出一个元素,就把其相应的左右孩子放入队列中(null 的不用放入)。

代码:

   public static void levelorder(TreeNode root) {
        if (root == null) {
            return;
        }
        Queue<TreeNode> queue = new LinkedList<>();
        //先将根结点放入,再进行循环判断
        //1. 取出队首元素
        //2. 打印队首元素值
        //3. 将队首元素的左孩子和右孩子依次放入队列中,为 null 的结点不放入
        queue.offer(root);
        while (!queue.isEmpty()) {
            TreeNode p = queue.poll();
            System.out.println(p.toString());
            if (p.left != null) {
                queue.offer(p.left);
            }
            if (p.right != null) {
                queue.offer(p.right);
            }
        }
    }

二、int sizeOf(TreeNode root) :获取树中结点个数

思路:层序遍历,利用队列,每取出一个元素,size++

代码:

    public static int sizeOf(TreeNode root) {
        if (root == null) {
            return 0;
        }
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        int size = 0;
        while (!queue.isEmpty()) {
            TreeNode p = queue.poll();
            size++;
            if (p.left != null) {
                queue.offer(p.left);
            }
            if (p.right != null) {
                queue.offer(p.right);
            }
        }
        return size;
    }

三、 int  leafSizeOf(TreeNode root) :获取叶子结点的个数

思路:跟统计结点数类似,只有当是叶子结点时,size 才进行 +1

代码:

    public static int leafSizeOf(TreeNode root) {
        if (root == null) {
            return 0;
        }
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        int size = 0;
        while (!queue.isEmpty()) {
            TreeNode p = queue.poll();
            if (p.left == null && p.right == null) {
                size++;
            }
            if (p.left != null) {
                queue.offer(p.left);
            }
            if (p.right != null) {
                queue.offer(p.right);
            }
        }
        return size;
    }

四、带层数的层序遍历

1. 使用打包的方式: class TreeNodeWithLevel 

     使用打包的方式,新建一个类,将结点和该结点相应的层数作为属性放入该类中。使用是将TreeNode 替换成 TreeNodeWithLevel,并且向队列中添加元素时,传入结点的同时,传入 level 层数即可。(若 node 的层数为 level,那么 node 的左右孩子的层数就为 level + 1)

代码:

    static class TreeNodeWithLevel {
        public TreeNode node;
        public int level;

        public TreeNodeWithLevel(TreeNode node, int level) {
            this.node = node;
            this.level = level;
        }

        @Override
        public String toString() {
            return String.format("%s-%d",node.toString(),level);
        }
    }

    //层序遍历 (带层数)
    public static void levelorderWithLevel(TreeNode root) {
        if (root == null) {
            return;
        }
        Queue<TreeNodeWithLevel> queue = new LinkedList<>();
        queue.offer(new TreeNodeWithLevel(root,1));
        while (!queue.isEmpty()) {
            TreeNodeWithLevel node = queue.poll();
            TreeNode p = node.node;
            int level = node.level;
            System.out.println(node);
            if (p.left != null) {
                queue.offer(new TreeNodeWithLevel(p.left,level + 1));
            }
            if (p.right != null) {
                queue.offer(new TreeNodeWithLevel(p.right,level + 1));
            }

        }
    }

2. 使用两个队列:nodeQueue 和 levelQueue

     使用两个队列,一个队列存放结点,另一个队列存放相应的层数。需要注意的是两个队列对应的元素个数一样,所以在 while() 条件判断时,取任意一个队列的元素不为空即可。

代码:

    public static void levelorderWithLevel2(TreeNode root) {
        if (root == null) {
            return;
        }
        Queue<TreeNode> nodeQueue = new LinkedList<>();
        Queue<Integer> levelQueue = new LinkedList<>();

        nodeQueue.offer(root);
        levelQueue.offer(1);

        while (!nodeQueue.isEmpty()) {
            TreeNode p = nodeQueue.poll();
            int level = levelQueue.poll();
            System.out.println( p + " + " + level);

            if (p.left != null) {
                nodeQueue.offer(p.left);
                levelQueue.offer(level + 1);
            }
            if (p.right != null) {
                nodeQueue.offer(p.right);
                levelQueue.offer(level + 1);
            }
        }
    }

五、int getKLevelSize(TreeNode root , int k) :获取第 k 层结点的个数

思路:使用带层数的层序遍历,当从队列中取出的元素的 level == k 时,size++。 

代码:

    public static int getKLevelSize(TreeNode root,int k) {
        if (root == null) {
            return 0;
        }

        Queue<TreeNodeWithLevel> queue = new LinkedList<>();
        queue.offer(new TreeNodeWithLevel(root,1));

        //定义变量,记录 k 层结点的个数
        int size = 0;
        while (!queue.isEmpty()) {
            TreeNodeWithLevel node = queue.poll();
            TreeNode p = node.node;
            int level = node.level;

            if (level == k) {
                //说明是第 k 层了
                size++;
            }
            if (p.left != null) {
                queue.offer(new TreeNodeWithLevel(p.left,level + 1));
            }
            if (p.right != null) {
                queue.offer(new TreeNodeWithLevel(p.right,level + 1));
            }
        }
        return size;
    }

六、int heightOf(TreeNode root) :获取二叉树的高度

思路:使用带层数的层序遍历,返回最后一个加入队列结点的 level 值即可。

代码:

    public static int heightOf(TreeNode root) {
        if (root == null) {
            return 0;
        }
        Queue<TreeNodeWithLevel> queue = new LinkedList<>();
        queue.offer(new TreeNodeWithLevel(root,1));

        //定义一个变量记录 height
        //height 的值可以根据 level 确定
        int height = -1;
        while (!queue.isEmpty()) {
            TreeNodeWithLevel node = queue.poll();
            TreeNode p = node.node;
            int level = node.level;

            height = level;

            if (p.left != null) {
                queue.offer(new TreeNodeWithLevel(p.left,level + 1));
            }
            if (p.right != null) {
                queue.offer(new TreeNodeWithLevel(p.right,level + 1));
            }

        }
        //此时 height 就为最后一个 level ,即最大的 level
        return height;
    }

七、boolean isCompleteTree(TreeNode root):判断一棵树是否是完全二叉树

思路:将所有元素依次加入队列,当取出的元素为 null 时停止元素添加。因为二叉树碰到 null 有两种情况:

  • null 之后所有元素也都为 null,则说明是完全二叉树
  • null 之后还有元素,则说明不是完全二叉树

代码:

    public static boolean isCompleteTree(TreeNode root) {
        if (root == null) {
            return true;
        }
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);

        //循环终止的条件,从队列中取出的元素是 null
        while (true) {
            TreeNode p = queue.poll();
            if (p == null) {
                break;
            }
            //因为这里需要根据本身的树进行判断,所以不用再判断左右孩子是否为 null
            queue.offer(p.left);
            queue.offer(p.right);
        }

        //判断取出元素为 null 后,其后面是否还有元素,即判断后面元素是否 == null
        //当后面元素存在 != null 时,说明不是完全二叉树,返回 false
        //当后面元素都 == null 时,说明是完全二叉树,返回 true
        while (!queue.isEmpty()) {
            TreeNode q = queue.poll();
            if (q != null) {
                return false;
            }
        }
        return true;
    }

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值