数据结构课程设计哈弗曼编码译码
- 格式:doc
- 大小:61.00 KB
- 文档页数:8
哈夫曼编码译码一、需求分析在当今信息爆炸时代,如何采用有效的数据压缩技术节省数据文件的存储空间和计算机网络的传送时间已越来越引起人们的重视,哈夫曼编码正是一种应用广泛且非常有效的数据压缩技术。
哈夫曼编码是一种编码方式,以哈夫曼树—即最优二叉树,带权路径长度最小的二叉树,经常应用于数据压缩。
哈弗曼编码使用一张特殊的编码表将源字符(例如某文件中的一个符号)进行编码。
这张编码表的特殊之处在于,它是根据每一个源字符出现的估算概率而建立起来的(出现概率高的字符使用较短的编码,反之出现概率低的则使用较长的编码,这便使编码之后的字符串的平均期望长度降低,从而达到无损压缩数据的目的)。
哈夫曼编码的应用很广泛,利用哈夫曼树求得的用于通信的二进制编码称为哈夫曼编码。
树中从根到每个叶子都有一条路径,对路径上的各分支约定:指向左子树的分支表示“0”码,指向右子树的分支表示“1”码,取每条路径上的“0”或“1”的序列作为和各个叶子对应的字符的编码,这就是赫夫曼编码。
哈弗曼译码输入字符串可以把它编译成二进制代码,输入二进制代码时可以编译成字符串二、其主要流程图:三、设计要求:(1)哈夫曼树的建立;(2)哈夫曼编码的生成(3)编码文件的译码四、总结:通过这次的课程设计了解课程设计是培养学生综合运用所学知识,发现,提出,分析和解决实际问题,锻炼实践能力的重要环节,是对学生实际工作能力的具体训练和考察过程.随着科学技术发展的日新日异,当今计算机应用在生活中可以说得是无处不在。
因此作为二十一世纪的大学来说掌握计算机开发技术是十分重要的。
回顾起此次课程设计,至今我仍感慨颇多,的确,自从拿到题目到完成整个编程,从理论到实践,在整整一个星期的日子里,可以学到很多很多的的东西,同时不仅可以巩固了以前所学过的知识,而且学到了很多在书本上所没有学到过的知识。
通过这次课程设计使我懂得了理论与实际相结合是很重要的,只有理论知识是远远不够的,只有把所学的理论知识与实践相结合起来,从理论中得出结论,才能真正为社会服务,从而提高自己的实际动手能力和独立思考的能力。
在设计的过程中遇到问题,这毕竟独立做的,难免会遇到过各种各样的问题,同时在设计的过程中发现了自己的不足之处,对以前所学过的知识理解得不够深刻,掌握得不够牢固,比如说结构体……通过这次课程设计之后,一定把以前所学过的知识重新温故。
我表示感谢!同时,对给过我帮助的所有同学和各位指导老师再次表示忠心的感谢!五、源程序:#include <stdio.h>#include <stdlib.h> //要用system函数要调用的头文件#include<conio.h> //用getch()要调用的头文件#include <string.h>#define N 50 //义用N表示50叶节点数#define M 2*N-1 //用M表示节点总数当叶节点数位n时总节点数为2n-1 #define MAXSIZE 100typedef struct{char data; //结点值int weight; //权值int parent; //双亲结点int lchild; //左孩子结点int rchild; //右孩子结点}HTNode;typedef struct{char cd[N]; //存放哈夫曼码int start; //从start开始读cd中的哈夫曼码}HCode;void CreateHT(HTNode ht[],int n) //调用输入的数组ht[],和节点数n{int i,k,lnode,rnode;int min1,min2;for (i=0;i<2*n-1;i++)ht[i].parent=ht[i].lchild=ht[i].rchild=-1; //所有结点的相关域置初值-1 for (i=n;i<2*n-1;i++) //构造哈夫曼树{min1=min2=32767; //int的范围是-32768-32767lnode=rnode=-1; //lnode和rnode记录最小权值的两个结点位置for (k=0;k<=i-1;k++){if (ht[k].parent==-1) //只在尚未构造二叉树的结点中查找{if (ht[k].weight<min1) //若权值小于最小的左节点的权值{min2=min1;rnode=lnode;min1=ht[k].weight;lnode=k;}else if (ht[k].weight<min2){min2=ht[k].weight;rnode=k;}}}ht[lnode].parent=i;ht[rnode].parent=i; //两个最小节点的父节点是iht[i].weight=ht[lnode].weight+ht[rnode].weight; //两个最小节点的父节点权值为两个最小节点权值之和ht[i].lchild=lnode;ht[i].rchild=rnode; //父节点的左节点和右节点}}void CreateHCode(HTNode ht[],HCode hcd[],int n){int i,f,c;HCode hc;for (i=0;i<n;i++) //根据哈夫曼树求哈夫曼编码{hc.start=n;c=i;f=ht[i].parent;while (f!=-1) //循序直到树根结点结束循环{if (ht[f].lchild==c) //处理左孩子结点hc.cd[hc.start--]='0';else //处理右孩子结点hc.cd[hc.start--]='1';c=f;f=ht[f].parent;}hc.start++; //start指向哈夫曼编码hc.cd[]中最开始字符hcd[i]=hc;}}void DispHCode(HTNode ht[],HCode hcd[],int n) //输出哈夫曼编码的列表{int i,k;printf(" 输出哈夫曼编码:\n");for (i=0;i<n;i++) //输出data中的所有数据,即A-Z {printf(" %c:\t",ht[i].data);for (k=hcd[i].start;k<=n;k++) //输出所有data中数据的编码{printf("%c",hcd[i].cd[k]);}printf("\n");}}void editHCode(HTNode ht[],HCode hcd[],int n) //编码函数{char string[MAXSIZE];int i,j,k;scanf("%s",string); //把要进行编码的字符串存入string数组中printf("\n输出编码结果:\n");for (i=0;string[i]!='#';i++) //#为终止标志{for (j=0;j<n;j++){if(string[i]==ht[j].data) //循环查找与输入字符相同的编号,相同的就输出这个字符的编码{for (k=hcd[j].start;k<=n;k++){printf("%c",hcd[j].cd[k]);}break; //输出完成后跳出当前for循环}}}}void deHCode(HTNode ht[],HCode hcd[],int n) //译码函数{char code[MAXSIZE];int i,j,l,k,m,x;scanf("%s",code); //把要进行译码的字符串存入code数组中while(code[0]!='#')for (i=0;i<n;i++){m=0; //m为想同编码个数的计数器for (k=hcd[i].start,j=0;k<=n;k++,j++) //j为记录所存储这个字符的编码个数{if(code[j]==hcd[i].cd[k]) //当有相同编码时m值加1m++;}if(m==j) //当输入的字符串与所存储的编码字符串个数相等时则输出这个的data数据{printf("%c",ht[i].data);for(x=0;code[x-1]!='#';x++) //把已经使用过的code数组里的字符串删除{code[x]=code[x+j];}}}}void main(){int n=26,i;char orz,back,flag=1;char str[]={'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'}; //初始化int fnum[]={186,64,13,22,32,103,21,15,47,57,1,2,32,20,57,63,15,1,48,51,80,23,8,18,1,16}; //初始化HTNode ht[M]; //建立结构体HCode hcd[N]; //建立结构体for (i=0;i<n;i++) //把初始化的数据存入ht结构体中{ht[i].data=str[i];ht[i].weight=fnum[i];}while (flag) //菜单函数,当flag为0时跳出循环{printf("\n");printf(" **************************************");printf("\n ** A---------------显示编码**");printf("\n ** B---------------进行编码**");printf("\n ** C---------------进行译码**");printf("\n ** D---------------退出**\n");printf(" ****************************************");printf("\n");printf(" 请输入选择的编号:");scanf("%c",&orz);switch(orz){case 'a':case 'A':system("cls"); //清屏函数CreateHT(ht,n);CreateHCode(ht,hcd,n);DispHCode(ht,hcd,n);printf("\n按任意键返回...");getch();system("cls");break;case 'b':case 'B':system("cls");printf("请输入要进行编码的字符串(以#结束):\n");editHCode(ht,hcd,n);printf("\n按任意键返回...");getch();system("cls");break;case 'c':case 'C':system("cls");DispHCode(ht,hcd,n);printf("请输入编码(以#结束):\n");deHCode(ht,hcd,n);printf("\n按任意键返回...");getch();system("cls");break;case 'd':case 'D':flag=0;break;default:system("cls");}}}。