/*判别二叉树T是否为完全二叉树*/
定义:深度为k且含有n个结点的二叉树,如果其每个结点都与深度为k的满二叉树中的编号从1到n的结点一一对应,则成为完全二叉树。
判断条件:
1. 左、右子树都是完全二叉树2. 左子树的高度和右子树一样或大1
3. 若左子树比右子树高度大1,则右子树必须是满的(节点数等于2^高度-1)
4. 若左子树和右子树高度一样,左子树必须是满的
另外:
具有n个结点的完全二叉树的深度k满足:2^(k-1)-1 < n <= 2^k-1 ;//式1
满足式1的二叉树,就满足左右子树的高度差不大于2,(要么左子树高1,要么右子树高1,要么高度相等)
只要再判断二叉树的左子树高度不小于右子树
就可保证判断条件1、2、3、4都满足。
新的判断条件:
1.具有n个结点的完全二叉树的深度k满足:2^(k-1)-1 < n <= 2^k-1 ;
2.所有左子树高度不小于右子树
解决:
先求结点数,再求深度-->条件一;
递归判断所有左右子树是否满足-->条件2。
代码如下:
/**********
【题目】编写算法判别给定二叉树是否为完全二叉树。
二叉链表类型定义:
typedef struct BiTNode {
TElemType data;
struct BiTNode *lchild, *rchild;
} BiTNode, *BiTree;
可用队列类型Queue的相关定义:
typedef BiTree QElemType; // 设队列元素为二叉树的指针类型
Status InitQueue(Queue &Q);
Status EnQueue(Queue &Q, QElemType e);
Status DeQueue(Queue &Q, QElemType &e);
Status GetHead(Queue Q, QElemType &e);
Status QueueEmpty(Queue Q);
**********/
//求二叉树深度
int TreeDepth(BiTree T)//计算二叉树深度
{
if(T==NULL)//如果T为NULL,则深度为0,这也是递归的返回条件
return 0;
//如果T不为NULL,那么深度至少为1,所以left和right=1
int left=1;
int right=1;
left+=TreeDepth(T->lchild);//求出左子树的深度
right+=TreeDepth(T->rchild);//求出右子树深度
return left>right?left:right;//返回深度较大的那一个
}
//计算计算结点数
void CalNode(BiTree T,int &count){
count++;
if(T->lchild){
CalNode(T->lchild,count);
}
if(T->rchild){
CalNode(T->rchild,count);
}
}
//判断二叉树T的所有左子树的深度是否都不小于对应的右子树
Status isLdFar(BiTree T){
BiTree p = T;
Status tag = TRUE;
if(p&&tag){
int l = TreeDepth(T->lchild);
int r = TreeDepth(T->rchild);
if(r>l||isLdFar(T->lchild)==FALSE||isLdFar(T->rchild)==FALSE)tag = FALSE;
}
return tag;
}
Status CompleteBiTree(BiTree T)
/* 判别二叉树T是否为完全二叉树 */
{
int count=0,k;//节点数count,深度k
Status tag1,tag2;
//第一每一个根节点的左孩子的深度ld大于等于右孩子的深度 rd
tag1 = isLdFar(T);
//第二结点数count高度k满足关系式:pow(2,k-1)-1<count)&&(pow(2,k)-1>=count
if(T!=NULL)CalNode(T,count);
k = TreeDepth(T);
if((pow(2,k-1)-1<count)&&(pow(2,k)-1>=count))tag2 = TRUE;
else return tag2 = FALSE;
return (tag1&&tag2); //同时满足两条件才是完全二叉树
}