1.什么是完全二叉树
对满二叉树的结点进行连续编号,约定编号从根结点起,自上而下,自左而右。
若一棵深度为k的,有n个结点的二叉树,当且仅当其每一个点都与深度为k的满二叉树(2^k - 1 个结点)中编号为1到n的的结点一一对应时称之为完全二叉树。
也可以理解为:k-1层为满二叉树,k层所有叶子结点左边靠齐。
2.算法的实现
在 c实现链式存储二叉树和层次遍历 的层次遍历
若以NULL存储结点的左右子结点时树的描述如下
例1:
该树为深度k为3的非完全二叉树,层次遍历为:1 2 3 4 NULL 6 NULL NULL NULL NULL NULL
例2:
该树为深度k为3的完全二叉树,层次遍历为: 1 2 3 4 5 6 NULL NULL NULL NULL NULL NULL NULL
这里我们假设若是从后往前看当不为空时,再继续往前看若无NULL,则为完全二叉树,反之则为非完全二叉树
这只假设,所以问一问一颗完全二叉树为什么不为空的元素之前就一定无NULL呢
完全二叉树的可以理解为:k-1层满二叉树的,第k层所有结点左靠齐,所以只有k层前有那层结点存在缺左或右或左右结点都缺的那么不空元素之前一定存在NULL。k层结点左靠其,若中间有NULL则说明k-1层有结点缺儿子。若为完全二叉树则:k-1层满二叉树的,第k层所有结点左靠齐,层次遍历不为NULL结点前无NULL,之后全为空。
各种情况可以动手画画就知道了
#1. 这里我们可以用栈存按储遍历结果(即BITreeNode指针,空指针即空结点)实现如算法1
#2. 我们也可指针数组(BiTNode* node[MAX_SIZE])存储遍历结果,倒叙判断 实现如算法2
算法1:
Status IsCompleteBiTree(BiTree T){
printf("\n判断是否为完全二叉树");
SqQueueP sq;InitQueue(sq); //用于遍历使用的队列
SqStackP ss;InitStack(ss); //用于存储遍历结果的栈
EnQueue(sq, T);
while(!QueueEmpty(sq)){
BiTNode* temp = DeQueue(sq);
ss.Push(temp);
if(temp) {
printf(" %d ",temp->data);
EnQueue(sq, temp->lchird);
EnQueue(sq, temp->rchird);
}
}
//判断不NULL元素前是否有NULL
BiTNode* ptnode;
while(1){
ptnode=Pop(ss);
if(ptnode) break;
}
while(1){
ptnode=Pop(ss);
if(!ptnode) return FALSE;
}
return TRUE;
}
算法2:
Status IsCompleteBiTree(BiTree T){
printf("\n判断是否为完全二叉树");
SqQueueP sq;InitQueue(sq); //用于遍历使用的队列
BiTNode* node[MAX_SIZE];
EnQueue(sq, T);
int i = 0;
while(!QueueEmpty(sq)){
BiTNode* temp = DeQueue(sq);
node[i++] = temp;
if(temp) {
printf(" %d ",temp->data);
EnQueue(sq, temp->lchird);
EnQueue(sq, temp->rchird);
}
}
// 当前倒序判断指针存在后,之后的倒序判断若存在NULL则该树为不完全树
printf("\n判断结果(Yse or No) :");
int j = i-1;
for(; j >=0; j--){
if(node[j]) break;
else continue;
}
for(; j >= 0; j--){
if(node[j]) continue;
else{
printf("No");
return FALSE;
}
}
if(j==-1){
printf("Yse");
}
return TRUE;
}