k=t[j].weight,flag=j;
t[flag].parent=1;
returnflag;
}
voidselect(HuffmanTreet,inti,int*s1,int*s2)
{/*s1为最小的两个值中序号小的那个*/
intj;
*s1=min1(t,i);
*s2=min1(t,i);
if(*s1>*s2)
{
j=*s1;
*s1=*s2;
*s2=j;
}
}
voidHuffmanCoding(HuffmanTree&HT,HuffmanCode&HC,int*w,char*ch,intn)/*算法6.12*/
{/*w存放n个字符的权值(均>0),构造赫夫曼树HT,并求出n个字符的赫夫曼编码HC*/
intm,i,j,s1,s2,start;
unsignedc,f;
HuffmanTreep;
char*cd;
if(n<=1)
return;
m=2*n-1;
HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));/*0号单元未用*/
for(p=HT+1,i=1;i<=n;++i,++p,++w,++ch)
{
(*p).ch=*ch;
(*p).weight=*w;
(*p).parent=0;
(*p).lchild=0;
(*p).rchild=0;
}
for(;i<=m;++i,++p)
{(*p).ch='*';
(*p).parent=0;
}
for(i=n+1,j=1;i<=m;++i,j++)/*建赫夫曼树*/
{/*在HT[1~i-1]中选择parent为0且weight最小的两个结点,其序号分别为s1和s2*/
select(HT,i-1,&s1,&s2);
printf("第%d次比较min1与min2:
%d%d",j,HT[s1].weight,HT[s2].weight);
printf("\n");
HT[s1].parent=HT[s2].parent=i;
HT[i].lchild=s1;
HT[i].rchild=s2;
HT[i].weight=HT[s1].weight+HT[s2].weight;
}
/*从叶子到根逆向求每个字符的赫夫曼编码*/
HC=(HuffmanCode)malloc((n+1)*sizeof(char*));
/*分配n个字符编码的头指针向量([0]不用)*/
cd=(char*)malloc(n*sizeof(char));/*分配求编码的工作空间*/
cd[n-1]='\0';/*编码结束符*/
for(i=1;i<=n;i++)
{/*逐个字符求赫夫曼编码*/
start=n-1;/*编码结束符位置*/
for(c=i,f=HT[i].parent;f!
=0;c=f,f=HT[f].parent)
/*从叶子到根逆向求编码*/
if(HT[f].lchild==c)
cd[--start]='0';
else
cd[--start]='1';
HC[i]=(char*)malloc((n-start)*sizeof(char));
/*为第i个字符编码分配空间*/
strcpy(HC[i],&cd[start]);/*从cd复制编码(串)到HC*/
}
free(cd);/*释放工作空间*/
}
voidReadDataFile(char*fileName1,int*wt,char*chh)//读初始化文件容
{
FILE*fp1;
charch;intw,i=0;
if((fp1=fopen(fileName1,"r"))==NULL)
{
printf("\nerroronopen%s!
",fileName1);
exit
(1);
}
printf("\n文件容:
\n");
while(!
feof(fp1))
{
fscanf(fp1,"%c",&ch);
if(ch=='\n')continue;//读到换行符,跳过,读下一行
chh[i]=ch;
printf("ch=%c",ch);
fscanf(fp1,"%5d",&w);//fscanf中的格式化要加\n,文件指针才会指向下一行
wt[i]=w;
printf("weight=%5d\n",w);
i++;
}
fclose(fp1);
}
voidWriteDataFile(char*fileName1)//将初始化信息写入文件中
{
FILE*fp1;
charc;intweight;
if((fp1=fopen(fileName1,"w"))==NULL)
{
printf("\nerroronopen%s!
",fileName1);
exit
(1);
}
printf("请输入相关字符及字符的权值,#结束:
\n");
c=getchar();
while((c=getchar())!
='#')
{
fprintf(fp1,"%c",c);//将字符写入文件
scanf("%d",&weight);
fprintf(fp1,"%5d\n",weight);//将字符的权值写入文件,采用fprintf格式化写入
}
fclose(fp1);
}
voidWriteToBeTran(char*fileName2)//将初始化信息写入文件中
{
FILE*fp2;
charch;
inti=0;
if((fp2=fopen(fileName2,"w"))==NULL)
{
printf("\nerroronopen%s!
",fileName2);
exit
(1);
}
printf("请输入需要编译的文本,#结束:
\n");
ch=getchar();
ch=getchar();
while(ch!
='#')
{
fputc(ch,fp2);
ch=getchar();
}
putchar(10);
fclose(fp2);
}
voidReadToBeTran(char*fileName2,charstr[])//读初始化文件容
{
FILE*fp2;
charch;inti=0;
if((fp2=fopen(fileName2,"r"))==NULL)
{
printf("\nerroronopen%s!
",fileName2);
exit
(1);
}
while(!
feof(fp2))
{
fscanf(fp2,"%c",&ch);
if(ch=='\n')continue;//读到换行符,跳过,读下一行
str[i++]=ch;
}
str[i]='\0';
fclose(fp2);
}
voidWriteCode(char*fileName3,char*fileName4,HuffmanTree&HT,HuffmanCode&HC,intn)
{FILE*fp3,*fp4;
charch;
inti;
if((fp3=fopen(fileName3,"r"))==NULL)
{printf("\nerroronopen%s!
",fileName3);
exit(0);
}
if((fp4=fopen(fileName4,"w"))==NULL)
{printf("\nerroronopen%s!
",fileName4);
exit(0);
}
while(!
feof(fp3))
{
ch=fgetc(fp3);
for(i=1;i<=n;i++)
if(ch==HT[i].ch)
fprintf(fp4,"%s",HC[i]);
}
fclose(fp3);
fclose(fp4);
}
voidReadCode(char*fileName4)
{FILE*fp4;
charch;
if((fp4=fopen(fileName4,"r"))==NULL)
{printf("\nerroronopen%s!
",fileName4);
exit(0);
}
printf("\n输出编码后的文件容:
\n");
while(!
feof(fp4))
{
ch=fgetc(fp4);
printf("%c",ch);
}
fclose(fp4);
printf("\n");
}
voidyima(HuffmanTree&HT,intn,charstr4[],charhh[])
{inti,j,m=0;
for(i=0,j=2*n-1;str4[i]!
='\0';i++)
{
if(str4[i]=='0'&&HT[j].lchild!
=0)
{j=HT[j].lchild;
if(HT[j].lchild==0||HT[j].rchild==0)
{hh[m++]=HT[j].ch;j=2*n-1;}
}
elseif(str4[i]=='1'&&HT[j].rchild!
=0)
{j=HT[j].rchild;
if(HT[j].lchild==0||HT[j].rchild==0)
{hh[m++]=HT[j].ch;j=2*n-1;}
}
}
hh[m]='\0';
}
voidWriteCodeFile(char*fileName5)//将初始化信息写入文件中
{
FILE*fp5;
charch;
inti=0;
if((fp5=fopen(fileName5,"w"))==NULL)
{
printf("\nerroronopen%s!
",fileName5);
exit
(1);
}
printf("请输入需要译的代码,#结束:
\n");
ch=getchar();
ch=getchar();
while(ch!
='#')
{
fputc(ch,fp5);
ch=getchar();
}
putchar(10);
fclose(fp5);
}
voidReadCodeFile(char*fileName5,charstr4[])//读初始化文件容
{
FILE*fp5;
charch;inti=0;
if((fp5=fopen(fileName5,"r"))==NULL)
{
printf("\nerroronopen%s!
",fileName5);
exit
(1);
}
while(!
feof(fp5))
{ch=fgetc(fp5);
str4[i++]=ch;
}
str4[i]='\0';
fclose(fp5);
}
voidWriteTextFile(char*fileName6,charhh[])
{FILE*fp6;
charch;
inti;
if((fp6=fopen(fileName6,"w"))==NULL)
{printf("\nerroronopen%s!
",fileName6);
exit(0);
}
for(i=0;hh[i]!
='\0';i++)
{ch=hh[i];
fprintf(fp6,"%c",ch);
}
fclose(fp6);
}
voidReadTextFile(char*fileName6)
{FILE*fp6;
charch;
if((fp6=fopen(fileName6,"r"))==NULL)
{printf("\nerroronopen%s!
",fileName6);
exit(0);
}
printf("\n输出译码后的文件容:
\n");
while(!
feof(fp6))
{ch=fgetc(fp6);
printf("%c",ch);
}
fclose(fp6);
printf("\n");
}
4.将函数的测试和主函数组合成一个文件,取名为huffermanuse.cpp。
#include"huffermanpubuse.h"
#include"huffermandef.h"
#include"huffermanalgo.h"
voidmain()
{
HuffmanTreeHT;
HuffmanCodeHC;
int*wt,n,m,i,y,x,s1,s2;
charstr[100];
charstr1[100],str2[100],str3[100],str4[100],str5[100],str6[100];
char*chh;
charhh[100];
printf("请输入权值的个数(>1):
");
scanf("%d",&n);
m=2*n-1;
wt=(int*)malloc((n)*sizeof(int));
chh=(char*)malloc((n)*sizeof(char));
printf("请输入数据文件名:
");
scanf("%s",str1);
WriteDataFile(str1);
ReadDataFile(str1,wt,chh);
HuffmanCoding(HT,HC,wt,chh,n);
printf("nodeletterweightparentlchildrchild");
printf("\n");
for(i=1;i<=m;i++)
{printf("%4d%6c%7d%8d%8d%8d",i,HT[i].ch,HT[i].weight,HT[i].parent,HT[i].lchild,HT[i].rchild);
printf("\n");
}
printf("***********哈夫曼树编码译码***********\n");
printf("***********1.对哈夫曼树进行编码***********\n");
printf("***********2.对文本文件中的文本进行编码***********\n");
printf("***********2.对代码文件中的代码进行译码***********\n");
printf("***********3.感谢使用***********\n");
while(x)
{printf("请输入要实现功能的代码:
\n");
scanf("%d",&y);
switch(y)
{
case1:
printf("赫夫曼编码为:
\n");
for(i=1;i<=n;i++)
{printf("%c的编码为:
",*(chh+i-1));
puts(HC[i]);
}break;
case2:
printf("请输入文本文件名:
");
scanf("%s",str2);
WriteToBeTran(str2);
ReadToBeTran(str2,str);
printf("请输入文本编码存放文件名:
");
scanf("%s",str5);
WriteCode(str2,str5,HT,HC,n);
ReadCode(str5);
break;
case3:
printf("请输入代码文件名:
");
scanf("%s",str3);
WriteCodeFile(str3);
ReadCodeFile(str3,str4);
yima(HT,n,str4,hh);
printf("请输入译文存放文件名:
");
scanf("%s",str6);
WriteTextFile(str6,hh);
ReadTextFile(str6);
break;
case4:
printf("感谢使用!
\n");
x=0;
break;
default:
printf("error!
");break;
}
}
}
保存,编译,连接,运行。
七、实验结果:
八、实验总结及心得体会:
九、对本实验过程及方法、手段的改进建议:
报告评分:
指导教师签字:
批阅日期:
注意:
●实验报告以纸质文档形式上交。
实验报告将记入平时成绩;
●每次实验开始时,交上一次的实验报告,否则将扣除此次实验成绩。