哈夫曼编码译码器1_第1页
哈夫曼编码译码器1_第2页
哈夫曼编码译码器1_第3页
哈夫曼编码译码器1_第4页
哈夫曼编码译码器1_第5页
已阅读5页,还剩14页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、滁州学院课程设计报告课程名称: 数据结构设计题目:哈夫曼编码译码器 系 别:计算机科学与技术专 业:网络工程组 别: 第十组起止日期: 2011年4月28日 2011年5月23日 指导教师: 计算机科学与技术系2010年制课程设计题目哈夫曼编码译码器组长学号班级系别计算机科学与技术专业网络工程组员指导教师课程设计目的掌握哈夫曼编码译码器的构造以及懂得设计思想课程设计所需环境VC+环境课程设计任务要求基本了解哈夫曼编码译码器的构造原理课程设计工作进度计划序号起止日期工 作 内 容分工情况郭金华 4月28日5月23日收集资料及构建哈夫曼树和打开文件函数构建哈夫曼树和打开文件函数朱锟4月28日5月2

2、3日收集资料及构建哈夫曼树和打开文件函数构建哈夫曼树和打开文件函数刘强4月28日5月23日编辑小结和构建生成哈夫曼编码的函数构建能够统计文件中字符的函数及其意义朱开发4月28日5月23日编辑小结和构建生成哈夫曼编码的函数构建能够统计文件中字符的函数及其意义高鹏飞4月28日5月23日编辑哈夫曼译码器中的译码器函数编辑哈夫曼译码器中的的译码器函数曹探4月28日5月23日编辑哈夫曼译码器中的译码器函数等其他的相关事宜编辑哈夫曼译码器中的译码器函数等其他的相关事宜教研室审核意见:教研室主任签字: 年 月 日课程设计任务书目录 1 课程设计的目的和意义。3 2 需求分析。4 3 系统(项目)设计。4 设

3、计思路及方案。4 模块的设计及介绍。5 主要模块程序流程图。7 4 系统实现。7 主调函数。7 建立Huffman Tree。8 生成Huffman Tree。,。9 电文译码。10 5 小结。13 6系统调试。13 参考文献。13 附录 源程序。13。 1.课程设计的目的和意义随着人民生活水平的提高,科学的进步和通信技术的发展。人们在进行通信的同时要求做到信息交流的保密性和快速准确性,尤其是在军事和高端科技方面。为了解决上面所提出的问题、实现该目的,设计出了一种快速可靠的编码方式,即哈夫曼编码。哈夫曼编码的应用很广泛,利用哈夫曼树求得的用于通信的二进制编码称为哈夫曼编码。树中从根到每个叶子都

4、有一条路径,对路径的各分支约定:指制定左子树的分支表示“0”码,指向右子树的分支表示“1”码,去每条路径的“0”或“1”的序列作为和各个对应的字符编码,这就是哈夫曼树编码。利用哈夫曼树编码进行通信可以大大的提高信道利用率,缩短信息传输时间,降低传输成本。但是,这要求在发送端通过一个编码系统对传数据预先编码,在接收端将传来数据进行译码(复原)。通常我们把数据压缩的过程叫做编码,解压缩的过程叫做解码。电报通信是传递文字的二进制码形式的字符串。但在信息传递时,总希望总长度尽可能最短,即采用最短码。作为计算机系学生,我们应该很好的掌握这门技术。在课堂上,我们能够学到许多的理论知识,但我们很少有过自己动

5、手实践的机会!课程设计就是为解决这个问题提供了一个平台。在课程设计过程中,我们每个人选择一个课题,认真研究,根据课堂讲授内容,还可以增强我们独立思考能力和动手能力:通过编写实验代码和调试运行,我们可以逐步积累调试C程序的经验并逐渐培养我们的编程能力、用计算机解决实际问题能力。在课程设计过程中,我们不但有自己的独立思考,还借助各种参考文件来帮助我们完成系统。更为重要的是,我们同学之间加强了交流,在对问题的认识方面可以交换不同的意见。同时,师生之间的互动也随之改善,我们可以通过具体的实例来从老师那学到更多的知识数据结构课程具有比较强的理论性,同时也具有较强的可用性和实践性。课程设计是一个重要的教学

6、环节。我们在一般情况下都能够重视实验环节,但是容易忽略实验的总结,忽略实验报告的撰写。通过这次试验我们明白:作为一名大学生必须严格训练分析总结能力、书面表达能力,需要逐步培养书写实验报告以及科技论文的能力。只有这样,我们的综合素质会有好的提高。 2 需求分析课 题:哈夫曼编码译码器系统问题描述:打开一篇英文文章,统计该文章中每个字符出现的次数,然后以它作为权值,对每一个字符进行编码,编码完成再对其编码进行译码。问题补充:1. 从硬盘的一个文件里读出一段英语文章; 2. 统计这篇文章中的每个字符出现的次数; 3.以字符出现字数作为权值,构建哈夫曼树,并将哈夫曼树的存储结构的初态和终态进行输出;

7、4.对每个字符进行编码并将所编码写入文件然后对所编码进行破译。具体介绍:在本课题中,我们在硬盘E盘中预先建立一个filel.txt文档,在里面编辑一篇文章(大写)。然后运行程序,调用fileopen()函数读出该文章,显示在界面;再调用jsq()函数对该文章的字符种类进行统计,并对每个字符的出现次数进行统计,并且在界面上显示;然后以每个字符出现次数作为权值,调用ChuffmanTree()函数构建哈夫曼树;并调用print1()和print2()函数将哈夫曼的存储结构的初态和终态进行输出。然后调用HuffmanEncoding()函数对哈夫曼树进行编码,调用coding()函数将编码写入文件;

8、再调用decode()对编码进行译码,再输出到界面。至此,整个工作就完成了。测试数据:例如从文本中读到文章为:IAMASTUDENT。 译码后的字符串:IAMASTUDENTPress any key to continue3 系统(项目)设计(1)设计思路及方案本课题是用最优二叉树即哈夫曼树来实现哈夫曼编码译码器的功能。假设每种字符在电文中出现的次数为Wi,编码长度为Li,电文中有n种字符,则电文编码总长度为(W1*L1)+(W2*L2)+.(Wi*Li)。若将此对应到二叉树上,Wi为叶结点,Li为根结点到叶结点的路径长度。那么,(W1*L1)+(W2*L2)+.(Wi*Li) 恰好为二叉树

9、上带权路径长度。因此,设计电文总长最短的二进制前缀编码,就是以n种字符出现的频率作权,构造一棵哈夫曼树,此构造过程称为哈夫码编码。该系统将实现以下几大功能:从硬盘读取字符串,建立哈夫曼树,输出哈夫曼树的存储结构的初态和终态,输出各种字符出现的次数以及哈夫曼编码的译码等。(2)模块的设计及介绍从硬盘读取字符串Fileopen(参数) 实现命令; 打印输出;建立HuffmanTree通过三个函数来实现:void select(参数)初始化;for 接受命令; 处理命令; 说明:在htl.k中选择parent为0且权值最小的两个根结点的算法int jsq(参数) 初始化; for 接受命令; 处理命

10、令;说明:统计字符串中各种字母的个数以及字符的种类void ChuffmanTree()初始化; for 接受命令; 处理命令; 输出字符统计情况;说明:构造哈夫曼树输出哈夫曼树的存储结构的初态和终态分别调用print1()和print2()来实现void print1(参数) 初始化; 输出初态;说明:输出哈夫曼树的初态void print2(参数) for 输出终态; 说明:输出哈夫曼树的终态 哈夫曼编码和译码void HuffmanEncoding(参数) 定义变量; 处理命令; 说明:哈夫曼编码 char *decode(参数) 定义变量; while 接受命令; 处理命令; 说明:哈

11、夫曼译码 哈夫曼编码: 流程图解释:该流程图表示哈夫曼编码情况。首先初始化,Cd-start=0,start=num.然后进行编码,使用了一个三目运算符。Cd-start=(Tp.lchild=c)?0:1,即当cd-start=Tp.lchild=c时,cd-start=0;当cd-start=0;当cd-start=Tp.lchild!=c时,cd-start=1.这个编码循环一直到i=num时结束。 4 系统实现各模块关键代码及算法的解释: 主调函数 代码解释:这是main函数里的各个函数调用情况。 fileopen(string); /从C盘内中读取文件 num=jsq(string,

12、cnt,str); /统计字符种类及各类字符出现的频率 DhuffmanTree(HT,cnt,str); printf(“HuffmanTree的初态:n”); print1(HT); /输出哈夫曼树的初态 ChuffmanTree(HT,HC,cnt,str); /建立哈夫曼树 HuffmanEncoding(HT,HC); /生成哈夫曼编码 printf(“HuffmanTree的终态:n”); print2(“HuffmanTree的终态:n”); printf(“%sn”); /输出译码后的字符串 建立HuffmanTree 代码解释:该函数为在htl.k中选择patent为0且权值

13、最小的根结点的算法,其序号为s1和s2.void select (HuffmanTree T,int k,int &s1,int &s2) int i, j; s2=s1 for(i=1;i<=k;i+) if(Ti.weight<min1 &&Ti.patent=0) j=i; min1=Ti.weight;s1=j; min1=32767;for(i=1;i<=k;i+) if(Ti.weight<min1 &&Ti.patent=0 &&i!=s1) j=i; min1=Ti.weight;s2=j;

14、对所有的字母进行统计种类和出现的次数int jsp(char *s,int cnt,char str) int i ,j,k; char *p; int temp27;for(i=1;i<=26;i+) tempi=0;for(p=s;*p!=0;p+) if(*p>=A&&*p<=Z) k=*p-64;/找到该字母的位置 tempk+;/统计各种字符的个数for(i=1,j=0;i<=26;+i) if(tempi!=0) j+; strj=i+64; /送对应字母到数组中 cntj=tempi; /存入对应字母的权值return j; /j是输入字母

15、总数代码解释:下面函数用来构造哈夫曼树HT。首先初始化哈夫曼树,然后输入前面统计的各个结点的权值,用for循环来构造哈夫曼树。void ChuffmanTree(HuffmanTree HT,HuffmanCode HC,int cnt,char str) int i,s1 ,s2; for(i=1;i<=2*num-1;i+) /初始化HT,2*num-1是指哈夫曼所有的节点数目 HTi.lchild=0;HTi.rchild=0; HTi.patent=0;HTi.weight=0;for(i=1;i<=num;i+) /输入num个叶结点的权值 HTi.weight=cnti

16、;for(i=num+1;i<=2*num-1;i+) select(HT,i-1,s1,s2); HTs1.patent=i;HTs2.patent=i; HTi.lchild=s1;HTi.rchild=s2; HTiweight=HTs1.weight*HTs2.weight; /在htl.k中选择patent为0且权值最小的两个根结点,其序号为s1和s2,i为双亲for(i=0;i<=num;i+); /输入字符集中字符HCi.ch=stri; /字符种类i=1;while(i<=num) printf(“字符%c次数:%d”,HCi.ch,cnti+); /输出统计

17、的情况 生成Huffman编码并写入文件 代码解释:根据哈夫曼树T求哈夫曼编码H。 void HuffmanEncoding (HuffmanTree T,HuffmanCode H) int c,p,i; /c和p分别指示t中孩子和双亲 char cdn; /临时存放编码串 int start; /指示码在cd中的起始位置 cdnum=0; /最后一位(第num个)放上串结束符 for(i=1;i<=num;+i) start=num; /初始位置 c=i; /从叶子结点ti开始上溯 while(p=Tc.patent)>0) /直至上溯到tc是树根为止 Cd-start=(Tp

18、.lchild=c) ?0:1; c=p; /若tc是tp的左孩子则生成0;否则生成1Strcpy(Hi.bits,*cdestart);Hi.len=num-start;代码解释:对str所代表的字符串进行编码并写入文件。将翻译的二进制码写入文本文件。void coding(HuffmanCode HC, char *str)int i,j;FILE *fp;Fp=fopen(“codefile.txt”,”w”);while(*str) for(i=1;i<=num;i+) if(HCi.ch=*str) for(j=0;j<=HCi.len;j+) Fputc(HCI.bit

19、sj,fp); break;str+; fclose(fp);电文译码 代码解释:代码文件codefile。Txt的译码,将翻译的二进制码译成原来的字符。char *decode(HuffmanCode HC)FILE *fp;char str254; /假设原文本文件不超过254个字符char *p;static char cdn+1;int i,j,k=0,cjs;Fp=fopen(“codefile.txt”,”r”); /一只读的方式打开文本文档codefile。Txtwhile(!feof(fp) /feof(fp)判断文件是否真正结束,feof(fp)=1时文件结束 cjs=0;

20、For(i=0;i<num&&cjs=0&&!feof(fp);i+) Cdi= Cdi+1=0; Cdi=fgetc(fp); /数组接收从fp指针所指向文件中读入的一个字符 for(j=1;j<=num;j+) if(strcmp(HCj.bits,cd)=0) strk=HCj.ch; k+; cjs=1;break; /haffman编码和密码译码相比较strk=0;p=str;return p;5 系统调试本次测试是在我的电脑的E盘中建立一个名为file1.txt的文本文档,其中有大写字母IAMASTUDENT,期望程序能将其读出至界面并实

21、现其它相关的功能。 运行程序后,我们可以见到以下运行界面。输出哈夫曼树存储结构的初态 输出哈夫曼树存储结构的终态 输出译码后的字符 由此可见,此次测试很成功。我们能够将文本文档file1.txt中的文段读出,并将其统计输出字符种类和每种字符出现的频率。同时输出哈夫曼树存储结构的初态和终态。然后输出译码后的字符。 小结 -通过两周的课程设计是我对哈夫曼树以及哈夫曼编码有了更深的认识和理解,也使我更加明白了哈夫曼编码译码在信息技术中的重要性地位。 首先我谈谈我在设计期间我遇到的难点。开始的时候,代码中有许多的错误,特别是有一个“无法找到文件”的错误让我束手无策,最后还是屏蔽了定义的四个头文件然后慢

22、慢的改正错误才让我又看到了希望。然后在实现文章的读入时,由于对文件不是太熟悉,只好翻开C语言书本仿照其模式编写,但后来进入了死循环,最后的解决方式是把main函数里的一个do while循环去掉,在程序中,我还另外加了一个功能-输出哈夫曼树的存储结构的初态和终态。这使得我更加的明白了哈夫曼到底是怎么存储信息的。许多的错误让我明白了一个道理-细心是非常重要的。同时,对于编程者而言,思路清晰是相当重要的。在适当的时候和同学一起交流探讨是一个十分好的学习机会。请教老师也很重要,因为毕竟我们是新手,对于某些问题很难弄清楚。而且,某些错误对于我们来说有时候想半天都弄不来,但老师几下就搞好了,这样就更加有

23、效的节约了时间。这段时间里,可谓是酸甜苦辣都尝过。有时,为了一个错误而焦头烂额;有时,变成熬夜到凌晨两点;有时,连吃饭都是草草了事;但一旦程序运行成功,总会让我兴奋不已。通过这次课程设计,我看清楚了自己的编程功底和动手能力还不如人意,这主要是平时是实践太少的缘故。我想,在未来的暑假中,首先任务是编写一些程序。虽然我们网络工程专业的学生,但现在变成的能力太差了,毕竟多精通一门技术总是好事。在这个程序中,还有许多地方值得完善。比如,读出文本只能是大写的文档,空格和小写不能识别,更不用说是任意的ASCII码字符了。由于时间问题,暂时不能实现了。 参考文献【1】 严蔚敏,数据结构(C语言版),清华大学

24、出版社,2007【2】 苏仕华,数据结构课程设计,机械工业出版社,2007【3】 谭浩强,C语言程序设计教程,高等教育出版社,2006附录:源程序# include< stdio.h># include<string.h># include<stdlib.h># include<fstream.h>/*类型相关变量的定义*# define n 100 /叶子结点数# define m 2*n-1 /哈夫曼树中的结点数typedef struct char ch; /相关的字母 char bits9; /存放编码位串 int len; /该字母编码

25、的长度CodeNode; /编码的类型typedef CodeNode HuffmanCoden+1; /所有的叶子结点的编码数组typedef struct int weight; /权值 int lchild,rchild,parent; /左右孩子及双亲指针HTNode; /哈夫曼树结点的类型typedef HTNode HuffmanTreem+1; /0号单元不用int num; /统计每种字母出现的次数和种类数目/建立HuffmanTree/ void select(HuffmanTree T,int k,int &s1,int &s2) /在ht1.k中选择par

26、ent为0且权值最小的两个根结点的算法 /其序号为s1和s2 int i,j;int min1=101; /min1的数字无何意义只是初始值之后用来记录权值,i为循/环 /最小权值的下标,k为数组结点的总数 for(i=1;i<=k;i+) if (Ti.weight<min1 &&Ti.parent=0) j=i; min1=Ti.weight;/赋权值 s1=j; min1=32767;/找到权值最小的其中之一 for (i=1; i<=k; i+) if(Ti.weight<min1 &&Ti.parent=0 &&

27、 i!=s1)/不让s2和s1的数组下标重合 j=i ; min1=Ti.weight;/找到权值最小的其中之一 s2=j ;int jsq(char *s, int cnt ,char str)/str存放所有字符,cnt来存放每种字母的权值 /统计字符串中各种字母的个数以及字符的种类,s为数组/的首地址指针 int i,j,k; char *p; int temp27; /存每种字母的个数 for(i=1;i<=26;i+) tempi=0; /初始化为0 for(p=s;*p!='0'p+) if(*p>='A' &&*p<

28、;='Z' ) k=*p-64; /找到字母在数组中的下标 tempk+; /字母个数累加 for(i=1,j=0;i<=26;+i) if( tempi !=0) j+; /j为字母的总数 strj=i+64; /送对应的字母到数组中 cntj=tempi; /存入对应字母的权值 return j; /j是输入字母总数void ChuffmanTree(HuffmanTree HT,HuffmanCode HC,int cnt, char str) /构造哈夫曼树HT int i,s1,s2; for(i=1;i<=2*num-1;i+) /初始化HT,2*num

29、-1是指哈夫曼树所有的结点数目 HTi.lchild=0;HTi.rchild=0; /初始化为根结点 HTi.parent=0;HTi.weight=0; /初始化为根结点 for(i=1;i<=num;i+) /输入num个叶子结点的权值 HTi.weight=cnti; /赋权值 for(i=num+1;i<=2*num-1;i+) select(HT,i-1,s1,s2); /在ht1.k中选择parent为0且权值最小的两个根结点 HTs1.parent=i;HTs2.parent=i; /其序号为s1和s2 HTi.lchild=s1;HTi.rchild=s2; /i

30、为双亲 HTi.weight=HTs1.weight+HTs2.weight; for(i=0;i<=num;i+) /输入字符集的中字符 HCi.ch=stri; /字符的种类 i=1;while(i<=num) printf("字符%c次数:%dn",HCi.ch,cnti+);/*生成Huffman编码并写入文件*void HuffmanEncoding(HuffmanTree T,HuffmanCode H) /根据哈夫曼树T求哈夫曼编码H int c,p,i; /c和p分别指示t中孩子和双亲 char cdn; /临时存放编码串,n为字母总数 int

31、start; /指示码在cd中的起始位置 cdnum='0' /num为叶子结点的总数 for(i=1;i<=num;+i) /对所有的叶子节点进行大循环的编码 start=num; /重最后的叶子结点上溯编码 c=i; /从叶子结点ti开始上溯 while(p=Tc.parent)>0) /直至上溯到tc是树根为止 /若tc是tp的左孩子,则生成0,否则生成1 cd-start=(Tp.lchild=c)?'0':'1' c=p; /使得可以进行循环 strcpy(Hi.bits,&cdstart); Hi.len=num-

32、start; void coding(HuffmanCode HC,char *str) /对str所代表的字符串进行编码并写入文件 int i,j; FILE*fp; /定义文件的指针 fp=fopen("codefile.txt","w"); /打开文件的函数 while (*str) for(i=1;i<=num;i+) if(HCi.ch=*str) for(j=0;j<=HCi.len;j+) fputc(HCi.bitsj,fp); break; str+; fclose(fp); /关闭文件/*电文译码*char *decode

33、(HuffmanCode HC) /读出编码文件的译码/代码文件codefile.txt的译码 FILE*fp; /定义文件指针 char str254; /假设原文本文件不超过254个字符 char *p; /定义字符串的指针 static char cdn+1; int i,j,k=0,cjs; fp=fopen("codefile.txt","r"); / 打开文件 while(!feof(fp) /feof(fp)判断文件是否真正结束,feof(fp)=1时文件结束 cjs=0;/作为返回值 for(i=0;i<=num&&

34、cjs=0 && !feof(fp);i+) cdi=' 'cdi+1='n' cdi=fgetc(fp); /数组接收从fp指针所指向文件中读入的一个字符 for(j=1;j<=num;j+) if(strcmp(HCj.bits,cd)=0) /haffman编码和密码译码相比较 strk=HCj.ch; k+; cjs=1;break; strk='0' /令最后的字符串的字符为0 p=str; /将str的头指针赋给了p return p; /*输出HuffmanTree存储结构*void print1(Huffma

35、nTree HT) int x; for(x=1;x<=2*num-1;x+) HTx.parent=0; HTx.lchild=0; HTx.rchild=0; printf("%11d %dt%dn",HTx.weight,HTx.parent,HTx.lchild,HTx.rchild); printf("-n");void print2(HuffmanTree HT) int k; for(k=1;k<=2*num-1;k+) printf("%dt%dt%dn",HTk.weight,HTk.parent,HTk.lchild,HTk.r

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论