点点小屋

博客园 首页 新随笔 联系 订阅 管理

调试实例:

图一:ABDH..I..EJ..K..CF..G..(扩展先序遍历输入二叉树)


图二:ABDH..I..EJ...CF.K..G.. (扩展先序遍历输入二叉树)


实现完全二叉树的判断算法

//判断完全二叉树算法描述
//用广度优先扫描二叉树发现非正常点后开始扫描后面剩余队列中的节点的子节点

#include<stdio.h>
#include<stdlib.h>

//二叉树数据结构
typedef struct Node
{
char data;
struct Node *LChild;
struct Node *RChild;
struct Node *Parent;
}BiNode,*BiTree;

//含头尾指针的链队列数据结构
typedef struct QueueNode
{
BiTree data;
struct QueueNode *next;
}LinkQueueNode;

typedef struct
{
LinkQueueNode *front;
LinkQueueNode *rear;
}LinkQueue;

//函数声明
void Print(BiTree *root);
void Choose(int choice,BiTree *root);
void ReadPreOrder(BiTree *root);
void PrintPreOrder(BiTree root);
int CompleteBinaryTree(BiTree root);
int InitQueue(LinkQueue *Q);
int EnterQueue(LinkQueue *Q,BiTree x);
int DeleteQueue(LinkQueue *Q);

//主函数
int main()
{
BiTree root;
    root=NULL;//初始化 无头结点

system("color a");
Print(&root);
while(true)
{
   printf("Press enter to continue.........");
   getchar();
   getchar();
   system("cls");
   Print(&root);
}
return 0;
}

void Print(BiTree *root)
{
int choice;
printf("Made By 杨梅树的盔甲~O(∩_∩)O~\n");
printf("---------------------\n");
printf("使用说明:本程序可实现基于队列的广度优先遍历算法判断完全二叉树.\n");
printf("---------------------\n");
printf("1.输入扩展先序遍历序列并建立对应的二叉树.\n");
printf("2.打印当前的二叉树的扩展先序遍历序列.\n");
printf("3.判断当前的二叉树是否为完全二叉树.\n");
printf("4.按其它任意键退出.\n");
printf("---------------------\n");

printf("请选择你要的操作:");
scanf("%d",&choice);
getchar();//此处getchar存储回车,避免对后面函数的影响!(很重要!)
Choose(choice,root);
}

void Choose(int choice,BiTree *root)
{
switch(choice)
{
case 1:
   ReadPreOrder(root);
   break;
case 2:
   PrintPreOrder(*root);
   printf("\n");
   break;
case 3:
   if(CompleteBinaryTree(*root))
   {
    printf("当前二叉树是完全二叉树!\n");
   }
   else{
    printf("当前二叉树不是完全二叉树!\n");
   }
   break;
default:
   exit(0);
}
}

void ReadPreOrder(BiTree *root)
//先序遍历二叉树,root为指向二叉树(或某一子树)根结点的指针
{
char ch;
ch=getchar();//使用getchar输入时必须谨记前面有没有多余的回车
if(ch=='.')
{
   (*root)=NULL;
}
else
{
   (*root)=(BiNode *)malloc(sizeof(BiNode));
   (*root)->data=ch;
   ReadPreOrder(&((*root)->LChild));
   ReadPreOrder(&((*root)->RChild));
}
}

void PrintPreOrder(BiTree root)
{
if(root!=NULL)
{
   printf("%c",(root)->data);
   PrintPreOrder(root->LChild);
   PrintPreOrder(root->RChild);
}
else
{
   printf(".");
}
}

//完全二叉树判断函数
//先利用队列找出二叉树中第一个没有包含两个孩子的节点(即第一个非正常节点)
//从第一个非正常节点后面开始出队的所有节点均不含子节点则该二叉树为完全二叉树
int CompleteBinaryTree(BiTree root)
{
int flag;
LinkQueue BiNode;//创建队列
InitQueue(&BiNode);//初始化队列
EnterQueue(&BiNode,root);//将根节点入队
while(BiNode.front!=BiNode.rear)//当队列不为空时进行广度优先扫描二叉树
//当发现非正常节点时跳出循环
{
   if(BiNode.front->next->data->LChild!=NULL&&BiNode.front->next->data->RChild!=NULL)
   //当左右孩子均有
   {
    //左右孩子入队
    EnterQueue(&BiNode,BiNode.front->next->data->LChild);
    EnterQueue(&BiNode,BiNode.front->next->data->RChild);
    DeleteQueue(&BiNode);//节点出队
   }
   else
    break;
}//下面分三种情况讨论

//左孩子没有 右孩子没有,继续扫描
if(BiNode.front->next->data->LChild==NULL&&BiNode.front->next->data->RChild==NULL)
{
   DeleteQueue(&BiNode);
   while(BiNode.front!=BiNode.rear)
   {
    if(BiNode.front->next->data->LChild!=NULL || BiNode.front->next->data->RChild!=NULL)
     return false;
    DeleteQueue(&BiNode);
   }
   return true;
}
//左孩子有 右孩子没有,继续扫描
else if(BiNode.front->next->data->LChild!=NULL&&BiNode.front->next->data->RChild==NULL)
{
   EnterQueue(&BiNode,BiNode.front->next->data->LChild);
   DeleteQueue(&BiNode);
   while(BiNode.front!=BiNode.rear)
   {
    if(BiNode.front->next->data->LChild!=NULL || BiNode.front->next->data->RChild!=NULL)
     return false;
    DeleteQueue(&BiNode);
   }
   return true;
}
//左孩子没有 右孩子有,非完全二叉树
else if(BiNode.front->next->data->LChild==NULL&&BiNode.front->next->data->RChild!=NULL)
   return false;
}

//队列的初始化函数
int InitQueue(LinkQueue *Q)
{
//将Q初始化为一个空的链队列
Q->front=(LinkQueueNode *)malloc(sizeof(LinkQueueNode));
if(Q->front!=NULL)
{
   Q->rear=Q->front;
   Q->front->next=NULL;
   return true;
}
else
   return false;//溢出
}

//入队函数
int EnterQueue(LinkQueue *Q,BiTree x)
{

//将数据元素x插入到队列Q中
LinkQueueNode *NewNode;
NewNode=(LinkQueueNode *)malloc(sizeof(LinkQueueNode));
if(NewNode!=NULL)
{
   NewNode->data=x;
   NewNode->next=NULL;
   Q->rear->next=NewNode;
   Q->rear=NewNode;
   return true;
}
else
   return false;//溢出
}

//出队操作
int DeleteQueue(LinkQueue *Q)
{
//将队列Q的队头元素出队,并存放到x所指的存储空间中
LinkQueueNode *p;
if(Q->front==Q->rear)
   return false;//队列为空 均指向头结点
p=Q->front->next;
Q->front->next=Q->front->next->next;//队头元素p出队
if(Q->rear==p)//如果队中只有一个元素p,则p出队后成为空队
{
   Q->rear=Q->front;
}
free(p);//释放存储空间
return true;
}

posted on 2009-12-23 17:46  点点小屋  阅读(2233)  评论(0)    收藏  举报