二叉树操作系统(哈夫曼树)头文件部分:
int a[1000];
BTree CreateHuf(ElemType a[],int n) //根据数组a中n 个权值建立一棵哈夫曼树,返回树根指针
{
int i,j;
BTree *t1,t2;
t1=(BTree *)malloc(n*sizeof(BTree)); //二级指针
/* for(i=0;i<n;i++)
t1[i]=(BTree)malloc(sizeof(BTNode));*/
for(i=0;i<n;i++) //初始化t1指针数组,构建n棵只含有根节点的树
{
t1[i]=(BTree)malloc(sizeof(BTNode));
t1[i]->ans=a[i]; //n个叶子节点的权重
t1[i]->lchild=NULL;
t1[i]->rchild=NULL; //各个叶子节点的初始化操作
}
for(i=1;i<n;i++) //向上取n-1次父亲节点,模拟哈夫曼树的过程就知道了
{
int First_min=-1,Second_min; //c表示森林中权值最小的根节点的下标,d表示权值第二小的根节点的下标
for(j=0;j<n;j++) //让c,d分别指向森林中的第一棵树和第二棵树
{
if(t1[j]!=NULL&&First_min==-1)
{ //t1[j]不到数组的尾部不可能是空指针
First_min=j;
continue; //即第一次后就有c!=-1了
}
if(t1[j]!=NULL)
{
Second_min=j;
break; //注意break
}
}
for(j=Second_min;j<n;j++) //从森林中找出权值最小的两棵树
{
if(t1[j]!=NULL)
{
if(t1[j]->ans<t1[First_min]->ans)
{
Second_min=First_min;
First_min=j;
}
else if(t1[j]->ans<t1[Second_min]->ans)
Second_min=j;
}
}
t2=(BTree)malloc(sizeof(BTNode)); //将找出的两棵树合并成一棵树
t2->ans=t1[First_min]->ans+t1[Second_min]->ans;
t2->lchild=t1[First_min]; //左孩子存放最小的能够一定程度上是最优二叉树是唯一的
t2->rchild=t1[Second_min];
t1[First_min]=t2;
t1[Second_min]=NULL;
}
free(t1);
return t2; //返回整个哈夫曼树的树根
}
void Print_BTree(BTree root)
{
if(root!=NULL)
{
printf("%d", root->ans); //输出根结点的值
if(root->lchild!=NULL||root->rchild!=NULL)
{
printf("(");
Print_BTree(root->lchild); //输出左子树
if(root->rchild!=NULL)
printf(",");
Print_BTree(root->rchild); //输出右子树
printf(")");
}
}
}
void Hufcoding(BTree root,int len,FILE *fp,FILE *fp2) //编码
{
static int c[10]; //如果我这里不加static那么这里就是自动局部变量,每次递归到这里后又重新分配内存空间大小
int i;
if(root!=NULL) //树不为空
{
if(root->lchild==NULL&&root->rchild==NULL) //为叶子节点就打印出来
{
fprintf(fp,"%d\n",root->ans);
for(i=0;i<len;i++)
{
fprintf(fp,"%d",c[i]);
fprintf(fp2,"%d",c[i]);
}
fprintf(fp,"%c",'\n');
}
else //访问到非叶子结点时分别向左右子树递归调用,并把分支上的0、1编码保存到数组a
{
c[len]=0;
Hufcoding(root->lchild,len+1,fp,fp2);
c[len]=1; //c[]是标记数组吗
Hufcoding(root->rchild,len+1,fp,fp2);
}
}
}
void Decoding_HuffumanTree(BTree root,FILE *fp1) //根据哈夫曼树的结构+编码序列得出译码序列
{
FILE *fp3;
if((fp1=fopen("coding.txt","r"))==NULL) //编码文件
{
printf("编码文件打开失败,请检查错误.\n");
return ;
}
if((fp3=fopen("Decoding.txt","w+"))==NULL) //译码文件
{
printf("译码文件创建失败,请检查错误.\n");
return ;
}
char *q=NULL;
BTree head=root;
q=(char *)malloc(sizeof(char)); //一颗哈夫曼树总共有2*n-1个节点
for(*q=fgetc(fp1);!feof(fp1);) //以字符方式进行文件读写操作
{
printf("%c",*q);
*q=fgetc(fp1); //fgetc()是每再进行一次读操作时才会自动移指针指向
}
rewind(fp1);
*q=fgetc(fp1);
while(head)
{
if(feof(fp1))
break;
if(*q=='0')
head=head->lchild;
if(*q=='1')
head=head->rchild;
if((NULL==head->lchild)&&(NULL==head->rchild))
{
fprintf(fp3,"%d\n",head->ans);
head=root;
}
*q=fgetc(fp1);
}
fclose(fp1);
fclose(fp3);
}
void Fuction_HuffumanTree(BTree root)
{
int chioce,n,i;
system("cls");
printf("\t 最优二叉书应用 \n");
printf("\t 1. 初始操作 \n");
printf("\t 2. 编码操作 \n");
printf("\t 3. 译码操作 \n");
printf("\t 4. 打印操作 \n");
printf("\t 0. 退出操作 \n");
printf("请输入相应操作: \n");
scanf("%d",&chioce);
while(!(chioce>=0&&chioce<=4))
{
printf("输入有问题,请重新输入:");
scanf("%d",&chioce);
}
while(chioce!=0)
{
switch(chioce)
{
case 1:
printf("请输入叶子节点的个数: \n");
scanf("%d",&n);
printf("请输入各个叶子节点所带有的权重:\n");
for(i=0;i<n;i++)
scanf("%d",&a[i]);
root=CreateHuf(a,n);
printf("已完成最优二叉树的构建过程!!!\n");
break;
case 2:
FILE *fp,*fp2;
if((fp=fopen("123.txt","w+"))==NULL)
{
printf("文件创建错误,请检查错误后重新来过.\n");
return ;
}
if((fp2=fopen("coding.txt","w+"))==NULL)
{
printf("文件创建错误,请检查错误后重新来过.\n");
return ;
}
Hufcoding(root,0,fp,fp2);
fclose(fp);
fclose(fp2);
printf("编码结果已写入123.txt文本文件中,请查看!!!\n");
printf("编码结果已写入coding.txt文本文件中,请查看!!!\n");
break;
case 3:
Decoding_HuffumanTree(root,fp2);
printf("\n译码结果已写入Decoding.txt文本文件中,请查看!!!\n");
break;
case 4:
printf("以广义表形式打印哈夫曼树各叶子节点关系: \n");
Print_BTree(root);
printf("\n");
break;
}
printf("请继续进行相应操作:");
scanf("%d",&chioce);
}
return ;
}
数据结构课程设计-二叉树操作系统
最新推荐文章于 2021-05-21 06:46:59 发布