完全二叉树也就是没有满的满二叉树,它的节点在每一层一定是连续分布的。如果出现哪一层中两个非空节点间隔一个空节点,那一定不是完全二叉树。如下图所示: 假设这棵完全二叉树有K层,因此我们可以总结一下完全二叉树的规律:
前K-2层:每个节点都有两个孩子,节点饱和前K-1层:节点肯定是饱和的—>到达了最大值第K-1层:不一定所有的节点都有孩子节点,如果有孩子节点,至少要是左孩子节点,有可能出现不饱和节点 方法一:从上面的规律中我们可以知道:
完全二叉树的前k-1层一定是包和节点,第k-1层就可能出现不饱和节点。判断二叉树是否为一棵完全二叉树的关键就是找到第一个不饱和节点,再判断后续节点与当前不饱和节点的关系(即:找到第一个不饱和的节点之后,后序的所有节点不能有孩子节点才是完全二叉树)。不饱和节点有: 只有左孩子只有右孩子没有孩子; 不饱和节点和后续节点的关系:是叶子节点(没有孩子)或者只有左孩子的节点:也就是这两种不饱和的节点出现之后还需要判断后面的节点是否有孩子只有右孩子没有左孩子:一定不是完全二叉树综上,我们把代码的步骤理一下:
空树:返回true树不为空:将根节点入队列,设置isLeafOrLeft=false(表示没有找到第一个不饱和节点),循环执行如下操作(循环条件:队列不为空):将队头元素出队列并标记:cur=queue.poll();找到第一个不饱和节点: 从第一个不饱和结点之后,所有节点不能有孩子,如果有左孩子或者右孩子:返回false 没有找到第一个不饱和节点,继续按照层序遍历寻找: cur节点(当前节点)左右孩子都存在:左孩子入队列,右孩子入队列cur只有左孩子:即找到第一个不饱和节点,标记isLeafOrLeft=truecur只有右孩子:找到不饱和节点,一定不是完全二叉树,返回falsecur是叶子节点:找到不饱和节点:标记isLeafOrLeft=true代码实现:
//判断是否为完全二叉树---》用层序遍历的思想一层一层找不饱和节点,也就是需要借队列public boolean isCompleteTree(BTNode root){ if(root==null) { return true; } Queue q=new LinkedList(); q.offer(root); //是叶子节点或者只有左孩子的节点,也就是这两种不饱和的节点出现之后还需要判断后面的节点是否有孩子 // 如果只有右孩子的不饱和节点一定不是完全二叉树// 一开始让不饱和节点置为false,找到之后设为trueboolean isLeafOrLeft=false;while(!q.isEmpty()) {BTNode cur = q.poll();//得到第一个不饱和节点之后if (isLeafOrLeft) { //从第一个不饱和结点之后,所有节点不能有孩子if (null != cur.left || null != cur.right) {System.out.println("该二叉树不是完全二叉树");return false;}}//没找到不饱和节点就继续按照层序遍历寻找else {//cur节点左右孩子都存在if (null != cur.left && null != cur.right) {q.offer(cur.left);q.offer(cur.right);} else if (null != cur.left) {//只有左孩子:找到不饱和节点,标记isLeafOrLeft=trueq.offer(cur.left);isLeafOrLeft = true;} else if (null != cur.right) {//只有右孩子:找到不饱和节点,一定不是完全二叉树,返回falseSystem.out.println("该二叉树不是完全二叉树");return false;} else {//cur是叶子节点:找到不饱和节点:标记isLeafOrLeft=trueisLeafOrLeft = true;}}}System.out.println("该二叉树是完全二叉树");return true;}上面这种方法在我们理清了判断是否为完全二叉树的关键之后,还是很容易写出的,同样是借助队列,还有另一种解题办法,来看看吧!
方法二:判断是否为完全二叉树的关键也是找到不饱和节点,但是第二个方法减少了各种不饱和节点的判断,在代码上减少了一定的代码量,同时思路也简洁了不少。
思路:
由于完全二叉树在每一层非空节点都是一个接一个连续分布的,不可能出现两个非空节点之间交叉一个空节点,因此:
我们可以通过层序遍历从上往下,从左往右将每一个节点(包括非空节点)都放到队列里在出队列的过程中,如果遇到空节点,则跳出循环跳出循环后,然后再判断队列中剩下的元素是否有非空节点:有非空节点:非完全二叉树;没有非空节点(全是空节点):完全二叉树。代码步骤:
1、树为空:返回true
2、树不为空:将二叉树的跟入队,并循环执行以下操作,循环条件:队列不为空;跳出循环条件:cur==null
取出队头元素,cur=queue.poll()如果有左孩子:入队列如果有右孩子:入队列3、当通过条件:cur==null跳出循环后,判断队列里边是否还有非空元素
如果有非空元素:不是完全二叉树没有非空元素:是完全二叉树代码:
public boolean isCompleteTree(BTNode root){if(root==null) return false;Queue queue=new Linklisted();queue.offer(root);while(!queue.isEmpty()){BTNode cur=queue.poll();if(cur==null){break;}else{if(cur.left!=null) queue.offer(cur.left);if(cur.right!=null) queue.offer(cur.right);}}//判断队列中剩余的元素是否为空while(!queue.isEmpty()){BTNode cur=queue.poll();if(cur!=null) return false;}return true;}