完全二叉树的定义:
若设二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层所有的结点都连续集中在最左边,这就是完全二叉树。
完全二叉树是由满二叉树而引出来的。对于深度为K的,有n个结点的二叉树,当且仅当其每一个结点都与深度为K的满二叉树中编号从1至n的结点一一对应时称之为完全二叉树。
一棵二叉树至多只有最下面的一层上的结点的度数可以小于2,并且最下层上的结点都集中在该层最左边的若干位置上,而在最后一层上,右边的若干结点缺失的二叉树,则此二叉树成为完全二叉树。
完全二叉树的判定:
叶节点只能出现在最下层和次下层,并且最下面一层的结点都集中在该层最左边的若干位置的二叉树
采用广度优先遍历的方法进行遍历,并使用队列这个结构操作数据.
只要当前节点有一个孩子不为空,那么就将它的左右孩子都压入队列,出队列第一次遇到NULL节点时,做一个标记,直到队列为空后面都再无非空节点出现,那么它就一定是完全二叉树;反之若第一次出现NULL节点后再出现非空节点,那么它一定就不满足完全二叉树的定义。
任意的一个二叉树,都可以补成一个满二叉树。这样中间就会有很多空洞。
在广度优先遍历的时候,如果是满二叉树,或者完全二叉树,这些空洞是在广度优先的遍历的末尾,
所以,但我们遍历到空洞的时候,整个二叉树就已经遍历完成了。
而如果,是非完全二叉树,我们遍历到空洞的候,就会发现,空洞后面还有没有遍历到的值。
这样,只要根据是否遍历到空洞,整个树的遍历是否结束来判断是否是完全的二叉树。
public boolean judge(BinarySearchTree<T> binarySearchTree){
BinaryNode<T> root=binarySearchTree.getRoot(); //获得树的根节点
if (root==null){
System.out.println("此树为空");
return true;
}
if (root.left == null && root.right ==null){
System.out.println("此树只有根节点");
return true;
}
//新建一个容量为50的队列
MyQueue q = new MyQueue(50);
boolean result= true;
boolean hasNoChild = false;
q.push(root);
//将根节点压入队列中
while (!q.isEmpty()){ //当队列不为空时
BinaryNode<T> current = (BinaryNode<T>)q.pop(); //获取当前队列第一个的元素,并删除,例如第一次执行时是获取树根并在队列中删除树根
if(hasNoChild){
if(current.left!=null||current.right!=null){ //至少有一个孩子的时候
result = false;
break;
}
}else{
if(current.left!=null&¤t.right!=null){ //有两个孩子
q.push(current.left);
q.push(current.right);
}else if(current.left!=null&¤t.right==null){ //只有左边的孩子
q.push(current.left);
hasNoChild = true;
}else if(current.left==null&¤t.right!=null){ //只有右边的孩子,此种情况不为完全二叉树,结果为false,并跳出循环
result = false;
break;
}else{
hasNoChild = true;
}
}
}
return result;
}