哈弗曼编码.docx
- 文档编号:11164411
- 上传时间:2023-02-25
- 格式:DOCX
- 页数:19
- 大小:76.71KB
哈弗曼编码.docx
《哈弗曼编码.docx》由会员分享,可在线阅读,更多相关《哈弗曼编码.docx(19页珍藏版)》请在冰豆网上搜索。
哈弗曼编码
福建工程学院
课程设计
课程:
数据结构课程设计
题目:
哈夫曼编/译码器
专业:
软件工程
班级:
1002
座号:
5号
姓名:
蔡梓楠
年月日
实验题目:
哈夫曼编/译码器
一、要解决的问题
本次课程设计要求:
1.从键盘输入字符集大小为你,n个字符和n个权值,建立哈夫曼树;
2.利用建好的哈夫曼树生成哈夫曼编码;
3.输入字符时,可以打印出哈夫曼编码;
4.输入哈夫曼编码时,可以输出对应的字符。
二、算法基本思想描述:
主要是哈夫曼树的建立以及哈夫曼编码的生成。
哈夫曼树的建立:
将所有数据建立为无双亲的二叉树,在所有无双亲二叉树中找出权值最小的两个数据,组合成为新二叉树,其双亲权值为两数据权值之和,然后继续在无双亲二叉树中寻找,循环下去;
哈夫曼编码在哈夫曼树的基础上建立,哈夫曼树中二叉树左孩子为0,有孩子为1;
三、设计
1.数据结构的设计和说明:
(1)数组结构
用于一开始存放输入数据和权值的数组,data表示数据为字符型,weight表示权值。
typedefstruct
{
chardata;
intweight;
}elemtype;
(2)哈夫曼树结构
哈夫曼树主要结构为二叉树,同样有左右儿子,哈夫曼树还有双亲,数据类型与权值,值得一提的是,结构中flag代表是否有双亲,“1”代表有;“0”代表没有。
typedefstruct
{
chardata;
intflag;
intweight;
intparent,lchild,rchild;
}htnode,*huffmantree;
2.模块结构图及各模块的功能:
赫夫曼编\译码器的主要功能是先建立赫夫曼树,然后利用建好的赫夫曼树生成赫夫曼编码后进行译码。
其主要结构如下图所示:
voidmain()/*主函数*/
voidreaddata(elemtype*w)/*读取字符信息*/
huffmantreecreatehuff(elemtype*w)/*建立哈弗曼树*/
HuffmanCodehuffmancode(huffmantreeht)/*哈弗曼编码*/
voidencoding(huffmantreeht,char**hc)/*测试编码*/
voiddecoding(huffmantreeht)/*译码*/
voidhf_print(elemtype*w)/*打印信息*/
voidhf_readdata(elemtype*w)/*读取自带字符频度*/
voidreadweight(elemtype*w)/*读取用户输入字符频度*/
voidExplain()/*功能提示说明*/
3.主要模块算法描述:
哈夫曼树的构成:
huffmantreecreatehuff(elemtype*w)/*建立哈弗曼树*/
{
开辟哈夫曼树类型空间,大小为2*n+1个;
将所有数据(一共n个数据)存入各自的哈夫曼树中,flag与parent置0;
其他剩余空间数据与权值置0;
for(当循环次数没有进行n次)
{
在所有flag为0的二叉树中找出权值最小的两个二叉树;
组合成为新二叉树
其双亲权值为两数据权值之和;
最小的两个二叉树flag为1;
}
将第0个二叉树所有数据置0;
打印哈夫曼树
}
四、源程序清单:
#include
#include
#include
#definen27/*字符集的容量*/
#defineMAXVALUE2000/*权值的最大值*/
#defineMAXNODE35/*哈夫曼树最多节点数*/
#defineMAXD100/*叶子节点数*/
typedefstruct/*字符集的元素结构*/
{
chardata;
intweight;
}elemtype;
typedefstruct/*哈夫曼树的元素结构*/
{chardata;
intflag;
intweight;
intparent,lchild,rchild;
}htnode,*huffmantree;
typedefchar**HuffmanCode;/*哈夫曼编码元素定义*/
voidreaddata(elemtype*w);/*读取字符信息*/
huffmantreecreatehuff(elemtype*w);/*建立哈弗曼树*/
HuffmanCodehuffmancode(huffmantreeht);/*哈弗曼编码*/
voidencoding(huffmantreeht,char**hc);/*测试编码*/
voiddecoding(huffmantreeht);/*译码*/
voidhf_print(elemtype*w);/*打印信息*/
voidhf_readdata(elemtype*w);/*读取自带字符频度*/
voidreadweight(elemtype*w);/*读取用户输入字符频度*/
voidExplain();/*功能提示说明*/
voidreaddata(elemtype*w)/*读取字符信息*/
{inti;
charzf;
w[0].data='';w[1].data='a';
w[2].data='b';w[3].data='c';
w[4].data='d';w[5].data='e';
w[6].data='f';w[7].data='g';
w[8].data='h';w[9].data='i';
w[10].data='j';w[11].data='k';
w[12].data='l';w[13].data='m';
w[14].data='n';w[15].data='o';
w[16].data='p';w[17].data='q';
w[18].data='r';w[19].data='s';
w[20].data='t';w[21].data='u';
w[22].data='v';w[23].data='w';
w[24].data='x';w[25].data='y';
w[26].data='z';
printf("Ifyouinputnewcharweightyourselfy/n/q:
\n");
zf=getchar();
while(zf!
='n'&&zf!
='y'&&zf!
='q')
zf=getchar();/*提取选择字符*/
switch(zf)
{
case'n':
hf_readdata(w);break;/*读取系统字符频度*/
case'y':
readweight(w);break;/*用户自己输入字符频度*/
case'q':
return;/*返回功能选择*/
}
hf_print(w);
return;
}
voidhf_readdata(elemtype*w)/*读取自带字符频度*/
{
w[0].weight=186;w[1].weight=64;
w[2].weight=13;w[3].weight=22;
w[4].weight=32;w[5].weight=103;
w[6].weight=21;w[7].weight=15;
w[8].weight=47;w[9].weight=57;
w[10].weight=1;w[11].weight=5;
w[12].weight=32;w[13].weight=20;
w[14].weight=57;w[15].weight=63;
w[16].weight=15;w[17].weight=1;
w[18].weight=48;w[19].weight=51;
w[20].weight=80;w[21].weight=23;
w[22].weight=8;w[23].weight=18;
w[24].weight=1;w[25].weight=16;
w[26].weight=1;
}
voidreadweight(elemtype*w)/*读取用户输入字符频度*/
{inti;
printf("Inputnewcharweight(nottoobig)\n");
for(i=0;i<27;i++)
{
printf("w[%d].data='%c';input:
w[%d].weight=?
\n",i,w[i].data,i);
scanf("%d",&w[i].weight);
printf("w[%d].data='%c';\tw[%d].weight=%d;\n",i,w[i].data,i,w[i].weight);
}
}
voidhf_print(elemtype*w)/*打印信息*/
{
inti;
for(i=0;i<27;i++)
{
printf("%c",w[i].data);
printf("%d\t",w[i].weight);
}
printf("\n");
}
huffmantreecreatehuff(elemtype*w)/*建立哈弗曼树*/
{
inti,j,x1,x2;
intm1,m2,m;
huffmantreeHT,p;
m=2*n-1;
HT=(huffmantree)malloc((m+1)*sizeof(htnode));
p=HT;
p++;
for(i=1;i<=m;i++,p++,w++)
{
if(i<=n)
{
p->data=w->data;
p->weight=w->weight;
}
else
{
p->data='\0';
p->weight=0;
}
p->parent=0;
p->lchild=0;
p->rchild=0;
p->flag=0;
}
for(i=1;i { m1=m2=MAXVALUE; x1=x2=0; p=HT; for(j=1;j<=n-1+i;j++) {if(p[j].weight { m2=m1; x2=x1; m1=p[j].weight; x1=j; } elseif(p[j].weight { m2=p[j].weight; x2=j; } } p[x1].parent=n+i; p[x2].parent=n+i; p[x1].flag=1; p[x2].flag=1; p[n+i].weight=p[x1].weight+p[x2].weight; p[n+i].lchild=x1; p[n+i].rchild=x2; } p[0].data=0; p[0].weight=0; p[0].flag=0; p[0].parent=0; p[0].lchild=0; p[0].rchild=0; system("cls"); for(i=0;i<=m;i++) { printf("%2d,data: %cweight: %4dparent: %3dlchild: %3drchild: %3d\n",i,p[i].data,p[i].weight,p[i].parent,p[i].lchild,p[i].rchild); if(i%15==0) { getchar(); system("cls"); } } printf("InputEnter: \n"); return(HT); Explain(); } HuffmanCodehuffmancode(huffmantreeht)/*哈弗曼编码*/ {char*cd; intc,i,f,start; HuffmanCodeHC;printf("11"); HC=(HuffmanCode)malloc((n+1)*sizeof(char*)); 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'; elsecd[--start]='1'; } HC[i]=(char*)malloc((n-start)*sizeof(char)); strcpy(HC[i],&cd[start]); } for(i=1;i<=n;i++)puts(HC[i]); free(cd); printf("\n"); return(HC); } voidencoding(huffmantreeht,char**hc)/*测试编码*/ { inti,j,k; charstring[MAXNODE]; system("cls"); fflush(NULL); printf("inputhuffmancodechar: eg: thisisprogrammaismyfavorite: \n"); printf("inputEnterend: \n"); gets(string); for(i=0;i { for(j=1;j<=n;j++) if(string[i]==ht[j].data) { k=j; break; } if(k<=0||k>MAXNODE) {printf("thereisn'tNO.%dchar\n",i,i); continue; } printf("%c\tweight=%2d\t%s\n",ht[k].data,ht[k].weight,hc[k]); } for(i=0;i { for(j=1;j<=n;j++) if(string[i]==ht[j].data) { k=j; break; } if(k<=0||k>MAXNODE) {printf("thereisn'tNO.%dchar\n",i,i); continue; } printf("%s",hc[k]); } } voiddecoding(huffmantreeht)/*译码*/ { chara[MAXD]; intm,i; system("cls"); printf("Input0/1: \n"); scanf("%s",a); m=2*n-1; for(i=0;a[i]! ='\0';i++) { if(a[i]=='0')m=ht[m].lchild; elsem=ht[m].rchild; if(m<=n) {printf("%c",ht[m].data); m=2*n-1; } } printf("\n"); printf("\n"); } voidExplain()/*功能提示说明*/ { printf("-------------Functionchice: -------------\n"); printf("-q: Quit: -\n"); printf("-r: Inputnewcharweight: -\n"); printf("-c: Createhuff: -\n"); printf("-e: HuffmancodeandEncoding: -\n"); printf("-d: Decoding: -\n"); printf("-----------------------------------------\n"); } main()/*主函数*/ { elemtypew[n];/*字符和频度集合类型*/ charch; huffmantreeht;/*哈夫曼树类型*/ HuffmanCodehc;/*编码类型*/ printf("-----------------------------------------------\n"); printf("-Wlcomeusehuffmanencodingdandecoding: -\n"); printf("-InputEntertocontinue: -\n"); printf("-----------------------------------------------\n"); ch=getchar(); while(ch! ='q')/*当键入’q’时程序运行结束*/ { Explain(); while(ch! ='r'&&ch! ='c'&&ch! ='e'&&ch! ='d'&&ch! ='q') ch=getchar();/*选取功能*/ switch(ch) {case'r': readdata(w);break;/*初始化(readdata),读取数据*/ case'c': ht=createhuff(w);hf_print(w);break;/*建立哈夫曼树(createhuff)*/ case'e': hc=huffmancode(ht);encoding(ht,hc);break;/*求字符集的哈夫曼编码(huffmancode)和求测试数据的编码(encoding)*/ case'd': decoding(ht);break;/*译码(decoding)*/ case'q': return;/*程序结束,返回*/ } ch=getchar(); } } 五、测试数据及测试结果(截图): 程序开始时打印欢迎界面,敲击回车继续: 打印选择界面,输入“r”时,为选择数据与权值输入,如若不选择自己输入权值,则系统内部自己已将各个数据赋好权值: 选择“c”时,建立哈夫曼树并打印出来,其顺序为数据,权值,双亲,左孩子,右孩子: 选择“e”时,进行哈夫曼编码,将想编译的原数据输入,如“abcd”。 先分项打印数据的权值和哈弗曼编码,后打印连续编码: 选择“d”时,对输入的哈弗曼编码进行译码,输入类如“1010100000”编码串,可以输出对应的字符: 六、课程设计总结即心得体会 我通过将近一周的数据结构课程设计论文的学习,从中认识到怎样将知识迁移运用,深刻的知道了理论应用和实际相互间的密切联系,感受到了理论知识固然重要,但是如果没有足够的实践经验,依旧无法将知识随意地应用于以后的工作中。 在今后的学习中,我一定会更加努力,认真,并且将理论与实践相结合。 做这个课程设计论文的时候,我遇到过许多的问题,比如说,写程序以及调试程序时,有很多地方的错误都搞不懂,不过在老师同学的帮助下,我成功的调试出了程序,并运行出了结果,当时我感觉非常有成就感。 还有就是C语言的时间运用上,自己确实也有很多大一时学的东西都忘了,而且有一些课余知识,不过我通过问同学、老师以及网上XX,最终我还是把它搞懂了,总之,觉得这门课程我收获了很多课堂外不能学到的东西。 非常让我受益匪浅! 通过这门课程的学习,我确实体会到了自己的知识还有很多不足之处和个人能力的十分有限,只有通过同学、老师间的密切配合才能完成一项不错的工作。 不过从中我也体会到了在学习中也有无限的乐趣,可以将现实生活中某一问题用程序编写出来并将以调试,得出结果原来是如此快乐的事情。 最后,在这里,我要十分感谢帮助过我的老师和同学们,是你们才让我顺利、成功的做出了这个课程设计! ! !
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 哈弗曼 编码