数据结构哈弗曼编码译码器课程设计1.docx
- 文档编号:27197618
- 上传时间:2023-06-28
- 格式:DOCX
- 页数:25
- 大小:240.33KB
数据结构哈弗曼编码译码器课程设计1.docx
《数据结构哈弗曼编码译码器课程设计1.docx》由会员分享,可在线阅读,更多相关《数据结构哈弗曼编码译码器课程设计1.docx(25页珍藏版)》请在冰豆网上搜索。
数据结构哈弗曼编码译码器课程设计1
数据结构与算法
课程设计报告
课程设计题目:
哈弗曼编码/译码器
专业班级:
信息与计算科学1001班
姓名:
学号:
设计室号:
理学院机房
设计时间:
2011-12-26批阅时间:
指导教师:
成绩:
哈夫曼算法的编码和译码系统
一.设计要求
2.功能设计流程
3.详细设计
4.调试
5.总结
6.参考文献
七.附录源代码
一.设计要求
设计一个利用哈夫曼算法的编码和译码系统,重复地显示并处理以下项目,直到选择退出为止。
1.1基本要求
1)将权值数据存放在数据文件(文件名为data.txt,位于执行程序的当前目录中)
2)分别采用动态和静态存储结构
3)初始化:
键盘输入字符集大小n、n个字符和n个权值,建立哈夫曼树;
4)编码:
利用建好的哈夫曼树生成哈夫曼编码;
5)输出编码;
6)设字符集及频度如下表:
字符空格ABCDEFGHIJKLM
频度1866413223210321154757153220
字符NOPQRSTUVWXYZ
频度5763151485180238181161
1.2进一步完成内容
1)译码功能;
2)显示哈夫曼树;
3)界面设计的优化。
二.功能流程图
2.1主要流程实现图
图的算法实现
初始化哈夫曼树
编码
文件
译码
文件
打印哈夫曼树
2.2主要菜单选择函数
Main函数中包裹四个主要功能函数,即
用于构造和初始哈夫曼树的HuffmanCoding函数
用于对指定文件进行编码的voidCoding函数
用于对哈夫曼编码进行译码的voidDecoding函数
用于在屏幕终端上显示哈弗满树的voidPrint_tree函数
其相互联系如下图所示
其中用于初始化哈夫曼树的Huffmancoding()函数包含两个子函数,即
(1)voidselect(HuffmanTreeHT,intj,int*s1,int*s2)
从目前已建好的赫夫曼树中选择parent为0且weight最小的两个结点
(2)voidInit()
输入n个字符及其对应的权值,根据权值建立哈夫曼树,其相互联系如图所示
HuffmanCoding()
voidselect
voidInit()
在本程序中,主界面为一个功能选择界面,根据提示,使用者可以选择不同的功能进行操作。
但由于在编制写程序的源代码中,出于方便编写的考虑,我们对一些功能所要引用的文件进行了提前的命名,因此在使用之前使用者应该提前知晓操作程序所需要的特定文件名,现总结如下:
Tobetrans.txt:
用于存储待编码的文本文件
Codefile.txt:
用于存储由Tobetrans.txt编码得到的哈弗曼编码信息
Textfile.txt:
用于存储由Codefile.txt译码得到的文本文件
hfmtree.txt:
用于存储哈夫曼树的文本文件
三.详细设计
3.1初始化哈夫曼树:
基本思想:
首先根据使用者输入的待编码字符和相应的权重值,再根据哈夫曼树的建立过程机型哈夫曼树的构造
主要步骤及主要功能函数:
(1)首先根据给定的权重构造n棵二叉树的森林,其中每个二叉树都只有一个权值为w[i]的根节点
(2)在森林中选取两个权值最小的根节点作为一个新二叉树的左右结点
其具体函数为
voidselect(HuffmanTreeHT,intj,int*s1,int*s2)//其中s1,s2为权值最小的两个根节点
for(i=1;i<=j;i++)
if(HT[i].parent==0)
{
*s1=i;
break;
}
for(;i<=j;i++)
if((HT[i].parent==0)&&(HT[i].weight *s1=i; HT[*s1].parent=1; 通过遍历所有节点找到权值最小的结点 (3)设新二叉树的根节点为左右子结点的权值和 其函数表达为 for(i=n+1;i<=m;++i) { select(HT,i-1,&s1,&s2); HT[s1].parent=i;HT[s2].parent=i; HT[i].lchild=s1;HT[i].rchild=s2; HT[i].weight=HT[s1].weight+HT[s2].weight; (4)从森林中删除选中的那两棵二叉树,同时加入新构造的那个二叉树 (5)重复上述步骤,得到所需的哈弗曼二叉树 3.2编码: 基本思想: 根据已构造好的哈夫曼树,对于每一个根节点从自身位置开始往根节点回溯,,并且规定哈夫曼树中的左节点代表0,有节点代表1,从而得到每个字符的哈弗曼编码 主要步骤及主要功能函数: 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]); } 3.3译码: 基本思想: 根据编码的具体过程,逆向推导。 从第一个数值开始,如果为零则代表沿左节点元素,如果为一则代表右节点方向 主要步骤及主要功能函数: if(*code=='0') find(HT,code,text,HT[m].lchild,m); else find(HT,code,text,HT[m].rchild,m); for(i=0;p[i]! ='\0';i++)//把译码好的字符存入文件textfile.txt中 fputc(p[i],fw); 3.4输出哈夫曼树: 基本思想: 以凸凹的形式表现哈夫曼树的结构。 首先统计叶子结点个数,然后构造一个矩阵,没有元素存在时用空格代替,否则将节点的权重值打印在终端 主要步骤及主要功能函数: (1)首先统计叶子节点的总个数 for(i=1;i<=2*n-1;i++) { for(j=0;T[i][j]! =0;j++) { if(T[i][j]=='') { printf(""); fputc(T[i][j],fp); } else {printf("%d",T[i][j]);fprintf(fp,"%d\n",T[i][j]);} } printf("\n"); } (2)建立矩阵,利用元素和空格构造一个凸凹的图像,直观的表现结构图,其中元素所在的列数即为在哈夫曼树中所在的层数 voidConvert_tree(unsignedcharT[100][100],ints,int*i,intj) { intk,l; l=++(*i); for(k=0;k T[l][k]=''; T[l][k]=HT[j].weight; if(HT[j].lchild) Convert_tree(T,s+1,i,HT[j].lchild); if(HT[j].rchild) Convert_tree(T,s+1,i,HT[j].rchild); T[l][++k]='\0'; } 3.5数据结构的定义 ////////////////////////////////////////////////////////////////////////////// /*定义赫夫曼树结点的结构体变量,存放结点的权值、字符、双亲、坐孩子和右孩子*/ typedefstruct{ intweight; charch;//增加一个域用于存放该节点的字符 intparent,lchild,rchild; }HTNode,*HuffmanTree; typedefchar**HuffmanCode;//指向赫夫曼编码的指针 四.调试 4.1菜单选择及初始化哈夫曼树界面 4.2编码 将编码结果写入codefile文件中 4.3译码 在textfile文件中写入译码结果 4.4以凹凸表形式打印哈夫曼树 为简便输入,我们选取几个较少的元素作为范例,对其进行输入和赋值,元素为{a.b.c.d.e.f.g.h.i.j},对应的权重值为{1.2.3.4.5.6.7.8.9.0},运行 五.总结 通过这次的综合训练让我对所学的知识加深了印象,要想学好c语言要重在实践,要通过不断的上机操作才能更好地学习它尤其是对算法有更深的认识。 对整个程序的设计,算法是非常重要的,设计程序的整体框架,就是利用算法进行设计,在短短的几天里,我们去图书馆或在网上查找了很多资料,学了一些以前没有接触过的函数,以此来完善程序的功能。 然而很多函数虽然用的语法没错,但是不能运用自如,为自己所用。 最后逐步完善各个函数的功能模块,同时算法也有了一定的认识。 这些都为以后的学习和实践,提高自身能力有很大的帮助,本次课设也锻炼我们的实践能力和提高了处理问题的能力,获益匪浅 六.参考文献 刘玉龙.《数据结构与算法》.电子工业出版社. 严蔚敏.《数据结构》(C语言版).清华大学出版社 严蔚敏等《数据结构题集》(C语言版).清华大学出版社 徐孝凯.数据结构实用教程(C/C++描述).北京: 清华大学出版社. 陈慧南.数据结构(使用C++语言描述).南京: 东南大学出版社. 殷人昆,陶永雷,谢若阳等.数据结构(用面向对象方法与C++描述).北京: 清华大学出版社. 七.附录源代码 #include #include #include ////////////////////////////////////////////////////////////////////////////// /*定义赫夫曼树结点的结构体变量,存放结点的权值、字符、双亲、坐孩子和右孩子*/ typedefstruct{ intweight; charch;//增加一个域用于存放该节点的字符 intparent,lchild,rchild; }HTNode,*HuffmanTree; typedefchar**HuffmanCode;//指向赫夫曼编码的指针 ////////////////////////////////////////////////////////////////////////////// /*本程序用到的函数原型*/ voidwelcome();//打印操作选择界面 voidHuffmanCoding(HuffmanTree&,char*,int*,int);//建立赫夫曼树的算法 voidselect(HuffmanTreeHT,intj,int*s1,int*s2);//从目前已建好的赫夫曼树中选择parent为0且weight最小的两个结点 voidInit();//输入n个字符及其对应的权值,根据权值建立哈夫曼树 voidCoding();//编码 voidDecoding();//译码 voidPrint_tree();//以凹凸表形式打印哈夫曼树 intRead_tree(HuffmanTree&);//从文件中读入赫夫曼树 voidfind(HuffmanTree&HT,char*code,char*text,inti,intm);//译码时根据01字符串寻找相应叶子节点的递归算法 voidConvert_tree(unsignedcharT[100][100],ints,int*i,intj);//将内存中的赫夫曼树转换成凹凸表形式的赫夫曼树 HuffmanTreeHT;//全局变量,指向存放赫夫曼树的存储空间 intn=0;//全局变量,存放赫夫曼树叶子结点的数目 intmain() { charselect; while (1) { welcome(); scanf("%c",&select); switch(select) { case'i': case'I': Init();break; case'c': case'C': Coding();break; case'd': case'D': Decoding();break; case't': case'T': Print_tree();break; case'e': case'E': exit (1); default: printf("Inputerror! \n"); } getchar(); } return0; } voidwelcome()//打印操作选择界面 { printf("****************************************\n"); printf("请选择如下操作\n"); printf("\n"); printf("I初始化哈夫曼树\n"); printf("C编码文件\n"); printf("D译码\n"); printf("T打印哈夫曼树\n"); printf("***************************************\n"); printf("***************************************\n"); system("colorA"); } ////////////////////////////////////////////////////////////////////////////////////// /*初始化函数,输入n个字符及其对应的权值,根据权值建立哈夫曼树,并将其存于文件hfmtree中*/ voidInit() { FILE*fp; inti,n,w[52];//w数组存放n个字符的权值 charcharacter[52];//存放n个字符 printf("\n输入字符个数n: "); scanf("%d",&n);//输入字符集大小 printf("输入%d个字符及其对应的权值: \n",n); for(i=0;i { charb=getchar(); scanf("%c",&character[i]); scanf("%d",&w[i]);//输入n个字符和对应的权值 } HuffmanCoding(HT,character,w,n);//建立赫夫曼树 if((fp=fopen("hfmtree.txt","w"))==NULL) printf("Openfilehfmtree.txterror! \n"); for(i=1;i<=2*n-1;i++) { if(fwrite(&HT[i],sizeof(HTNode),1,fp)! =1)//将建立的赫夫曼树存入文件hfmtree.txt中 printf("Filewriteerror! \n"); } printf("\n建立赫夫曼树成功,已将其存于文件hfmtree.txt中\n"); fclose(fp); } /////////////////////////////////////////////////////////////////////////////////// //////建立赫夫曼树的算法/////////////////////////////////////////////////////////// voidHuffmanCoding(HuffmanTree&HT,char*character,int*w,intn) { intm,i,s1,s2; HuffmanTreep; if(n<=1)return; m=2*n-1; HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode)); for(p=HT+1,i=1;i<=n;++i,++p,++character,++w) {p->ch=*character;p->weight=*w;p->parent=0;p->lchild=0;p->rchild=0;} for(;i<=m;++i,++p){p->ch=0;p->weight=0;p->parent=0;p->lchild=0;p->rchild=0;} for(i=n+1;i<=m;++i) { select(HT,i-1,&s1,&s2); HT[s1].parent=i;HT[s2].parent=i; HT[i].lchild=s1;HT[i].rchild=s2; HT[i].weight=HT[s1].weight+HT[s2].weight; } } /////////////////////////////////////////////////////////////////////////////// /*从HT[1]到HT[j]中选择parent为0且weight最小的两个结点,用s1和s2返回其序号*/ voidselect(HuffmanTreeHT,intj,int*s1,int*s2) { inti; //找weight最小的结点 for(i=1;i<=j;i++) if(HT[i].parent==0) {*s1=i;break;} for(;i<=j;i++) if((HT[i].parent==0)&&(HT[i].weight *s1=i; HT[*s1].parent=1; //找weight次小的结点 for(i=1;i<=j;i++) if(HT[i].parent==0) {*s2=i;break;} for(;i<=j;i++) if((HT[i].parent==0)&&(i! =*s1)&&(HT[i].weight *s2=i; } /////////////////////////////////////////////////////////////////////////////// /*对文件tobetrans中的正文进行编码,然后将结果存入文件codefile中*/ voidCoding() { FILE*fp,*fw; inti,f,c,start; char*cd; HuffmanCodeHC; if(n==0) n=Read_tree(HT);//从文件hfmtree.txt中读入赫夫曼树,返回叶子结点数 /////以下程序段求赫夫曼树中各叶子节点的字符对应的的编码,并存于HC指向的空间中 { 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]); } free(cd); } ///////////////////////////////////////////////////////////////////////////////////// if((fp=fopen("tobetrans.txt","rb"))==NULL) printf("Openfiletobetrans.txterror! \n"); if((fw=fopen("codefile.txt","wb+"))==NULL) printf("Openfilecodefile.txterror! \n"); chartemp; fscanf(fp,"%c",&temp);//从文件读入第一个字符 while(! feof(fp)) { for(i=1;i<=n;i++) if(HT[i].ch==temp)break;//在赫夫曼树中查找字符所在的位置 for(intr=0;HC[i][r]! ='\0';r++)//将字符对应的编码存入文件 fputc(HC[i][r],fw); fscanf(fp,"%c",&temp);//从文件读入下一个字符 } fclose(fw); fclose(fp); printf("\n对文件hfmtree.txt编码成功,结果已存入codefile.txt中。 \n\n"); } ///////////////////////////////////////////////////////////////////////// /*将文件codefile中的代码进行译码,结果存入文件textfile中*/ voidDecoding() { FILE*fp,*fw; intm,i; char*code,*text,*p; if(n==0) n=Read_tree(HT);//从文件hfmtree.txt中读入赫夫曼树,返回叶子结点数 if((fp=fopen("codefile.txt","rb"))==NULL) printf("Openfilecodefile.txterror! \n"); if((fw=fopen("textfile.txt","wb+"))==NULL) printf("Openfiletextfile.txterror! \n"); code=(char*)malloc(sizeof(char)); fscanf(fp,"%c",code);//从文件读入一个字符 for(i=1;! feof(fp);i++) { code=(char*)realloc(code,(i+1)*sizeof(char));//增加空间 fscanf(fp,"%c",&code[i]);//从文件读入下一个字符 } code[i-1]='\0'; /////////到此codefile.txt文件中的字符已全部读入,存放在code数组中 tex
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 数据结构 哈弗曼 编码 译码器 课程设计