哈夫曼编码译码数据结构课程设计报告书_第1页
哈夫曼编码译码数据结构课程设计报告书_第2页
哈夫曼编码译码数据结构课程设计报告书_第3页
已阅读5页,还剩18页未读 继续免费阅读

下载本文档

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

文档简介

1、数据结构课程设计题目:哈夫曼编码译码专业:通信工程 学号: 指导教师:吴泽晖目录目录 1一、需求分析 2二、设计要求 2三、概要设计 21、 流程图 22、 设计包含的几个部分 4四、详细设计 2五、显示结果 9.六、心得体会 10七、参考文献 11哈夫曼编码译码一、 需求分析在当今信息爆炸时代, 如何采用有效的数据压缩技术节省数据文件的存储空 间和计算机网络的传送时间已越来越引起人们的重视, 赫夫曼编码正是一种应用 广泛且非常有效的数据压缩技术。 哈夫曼编码是一种编码方式, 以哈夫曼树即 最优二叉树, 带权路径长度最小的二叉树, 经常应用于数据压缩。 哈弗曼编码使 用一特殊的编码表将源字符

2、(例如某文件中的一个符号) 进行编码。 这编码表的 特殊之处在于, 它是根据每一个源字符出现的估算概率而建立起来的 (出现概率 高的字符使用较短的编码, 反之出现概率低的则使用较长的编码, 这便使编码之 后的字符串的平均期望长度降低,从而达到无损压缩数据的目的) 。赫夫曼编码 的应用很广泛, 利用赫夫曼树求得的用于通信的二进制编码称为赫夫曼编码。 树 中从根到每个叶子都有一条路径, 对路径上的各分支约定: 指向左子树的分支表 示“ 0”码,指向右子树的分支表示“ 1”码,取每条路径上的“ 0”或“ 1”的序 列作为和各个叶子对应的字符的编码, 这就是赫夫曼编码。 哈弗曼译码输入字符 串可以把它

3、编译成二进制代码,输入二进制代码时可以编译成字符串。二、 设计要求对输入的一串电文字符实现赫夫曼编码, 再对赫夫曼编码生成的代码串进行 译码,输出电文字符串。 通常我们把数据压缩的过程称为编码, 解压缩的过程称 为解码。电报通信是传递文字的二进制码形式的字符串。 但在信息传递时, 总希 望总长度能尽可能短,即采用最短码。假设每种字符在电文中出现的次数为Wi,编码长度为Li,电文中有n种字符,则电文编码总长度为刀 WiLi。若将此对应 到二叉树上,Wi为叶结点的权,Li为根结点到叶结点的路径长度。那么,刀WiLi 恰好为二叉树上带权路径长度。因此 ,设计电文总长最短的二进制前缀编码, 就是以 n

4、 种字符出现的频率作权, 构造一棵赫夫曼树, 此构造过程称为赫夫曼编 码。设计实现的功能: (1) 赫夫曼树的建立; (2) 赫夫曼编码的生成; (3) 编 码文件的译码。三、 概要设计哈夫曼编 译码器的主要功能是先建立哈夫曼树,然后利用建好的哈夫曼树 生成哈夫曼编码后进行译码 。在数据通信中,经常需要将传送的文字转换成由二进制字符 0、1 组成的二 进制串,称之为编码。构造一棵哈夫曼树,规定哈夫曼树中的左分之代表 0,右 分支代表 1,则从根节点到每个叶子节点所经过的路径分支组成的 0和 1的序列 便为该节点对应字符的编码,称之为哈夫曼编码。最简单的二进制编码方式是等长编码。 若采用不等长编

5、码, 让出现频率高的 字符具有较短的编码, 让出现频率低的字符具有较长的编码, 这样可能缩短传送 电文的总长度。哈夫曼树课用于构造使电文的编码总长最短的编码方案。(1)其主要流程图如图 1-1 所示。开始是结点数是否大于1l<2*N?是输出根结点和权值将data和权值赋给ht调用SELECT函数计算根结点函数父结点为两子结点之和是否为根结点?是左子是否为空?否否是否为空输出两子结点和已构造的结点此时编码为0编码为1结束(2)设计包含的几个方面: 赫夫曼树的建立 赫夫曼树的建立由赫夫曼算法的定义可知, 初始森林中共有 n 棵只含有根结点的 二叉树。算法的第二步是: 将当前森林中的两棵根结点

6、权值最小的二叉树, 合并 成一棵新的二叉树;每合并一次,森林中就减少一棵树,产生一个新结点。显然 要进行 n1 次合并,所以共产生 n1 个新结点,它们都是具有两个孩子的分支 结点。由此可知,最终求得的赫夫曼树中一共有2n1个结点,其中n个结点是 初始森林的 n 个孤立结点。 并且赫夫曼树中没有度数为 1 的分支结点。 我们可以 利用一个大小为 2n-1 的一维数组来存储赫夫曼树中的结点。 赫夫曼编码要求电文的赫夫曼编码, 必须先定义赫夫曼编码类型, 根据设计要求和实际需要 定义的类型如下: typedet struct char ch; / 存放编码的字符 char bitsN 1; /存放

7、编码位串int len; / 编码的长度CodeNode; / 编码结构体类型 代码文件的译码译码的基本思想是: 读文件中编码, 并与原先生成的赫夫曼编码表比较, 遇到相 等时,即取出其对应的字符存入一个新串中。四、详细设计(1)赫夫曼树的存储结构描述为:#define N 50 /叶子结点数#define M 2*N-1 /赫夫曼树中结点总数typedef struct int weight; / 叶子结点的权值int lchild, rchild, parent; / 左右孩子及双亲指针HTNode; / 树中结点类型 typedef HTNode HuffmanTreeM+1;哈弗曼树的

8、算法void CreateHT(HTNode ht,int n) / int i,k,lnode,rnode;int min1,min2;for (i=0;i<2*n-1;i+)hti.parent=hti.lchild=hti.rchild=-1; / -1for (i=n;i<2*n-1;i+)/min1=min2=32767; /int lnode=rnode=-1;/lnode调用输入的数组 ht, 和节点数 n所有结点的相关域置初值构造哈夫曼树的围是 -32768 32767和 rnode 记录最小权值的两个结点位置for (k=0;k<=i-1;k+)只在尚未构造

9、二叉树的结点中查若权值小于最小的左节点的权值if (htk.parent=-1) /找if (htk.weight<min1)/min2=min1;rnode=lnode; min1=htk.weight;lnode=k;else if (htk.weight<min2) min2=htk.weight;rnode=k;两个最小节点的/ 两个最小节点的父节点的左节点htlnode.parent=i;htrnode.parent=i; / 父节点是 ihti.weight=htlnode.weight+htrnode.weight; 父节点权值为两个最小节点权值之和hti.lchil

10、d=lnode;hti.rchild=rnode; / 和右节点(2)哈弗曼编码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=hti.parent;while (f!=-1)/if (htf.lchild=c)/hc.cdhc.start-='0'else/hc.cdhc.start-='1'c=f;f=htf.parent;hc.start+;/start根据哈夫曼树求哈夫曼编码循序直到树根结点结束循环处理左

11、孩子结点处理右孩子结点指向哈夫曼编码 hc.cd 中最开始字符hcdi=hc;void DispHCode(HTNode ht,HCode hcd,int n) /int i,k;printf(" 输出哈夫曼编码 :n");for (i=0;i<n;i+) /printf(" %c:t",hti.data);for (k=hcdi.start;k<=n;k+)/printf("%c",hcdi.cdk);printf("n");void editHCode(HTNode ht,HCode hcd,int

12、 n) /char stringMAXSIZE;int i,j,k;scanf("%s",string); /数组中printf("n 输出编码结果 :n");for (i=0;stringi!='#'i+) /#for (j=0;j<n;j+)if(stringi=htj.data) / 号,相同的就输出这个字符的编码for (k=hcdj.start;k<=n;k+)输出哈夫曼编码的列表输出 data 中的所有数据,即 A-Z输出所有 data 中数据的编码编码函数把要进行编码的字符串存入 string为终止标志循环查找与

13、输入字符相同的编 printf("%c",hcdj.cdk);break; / 输出完成后跳出当前 for 循环 (3)哈弗曼译码void deHCode(HTNode ht,HCode hcd,int n) / char codeMAXSIZE;int i,j,l,k,m,x;scanf("%s",code); / 组中while(code0!='#')for (i=0;i<n;i+)m=0; /mfor (k=hcdi.start,j=0;k<=n;k+,j+) /j 个数if(codej=hcdi.cdk) / m+;i

14、f(m=j) / 符串个数相等时则输出这个的 data 数据 printf("%c",hti.data); for(x=0;codex-1!='#'x+) / 字符串删除codex=codex+j;(4)主函数译码函数把要进行译码的字符串存入 code 数为想同编码个数的计数器为记录所存储这个字符的编码当有相同编码时m值加1当输入的字符串与所存储的编码字把已经使用过的 code 数组里的void main()int n=26,i;char orz,back,flag=1;charstr='A','B','C',

15、'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=,64,13,2

16、2,32,103,21,15,47,57,1,2,32,20,57,63,15,1,48,51,80,23,8,18,1,16; / 初始化HTNode htM;/建立结构体HCode hcdN;/建立结构体for (i=0;i<n;i+)/把初始化的数据存入 ht 结构体中hti.data=stri;hti.weight=fnumi;while (flag) / 菜单函数,当 flag 为 0 时跳出循环( 5)显示部分源程序:printf("n");printf("*");显示编码 *") 进行编码 *") 进行译码 *&q

17、uot;) 退出 *n");printf("n* 1printf("n* 2printf("n* 3printf("n* 4printf("* *");printf("n");printf(" 请输入选择的编号 :");scanf("%c",&orz);switch(orz)case 'a':清屏函数case 'A':system("cls"); /CreateHT(ht,n);CreateHCode(ht

18、,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 &#

19、39;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");五、调试结果进入主菜单I 小 F; C+CTnTaii1b3LnTw

20、i:exaBSD1耳車耳*上卓承*冀# -*-+ J*-4 Jlj|l 4lj|l 4uj|l 4lj|l 4沖事齐卓齐車齐卓#木克A=+ H显示编码+-<+ 3进行编码杠+ 7一进行译码艸“二 -退出+耳 t 球 * * 北十:T*:K*乂* 北* * * * * *耳 * 辛耳* t请辑人诰揺的嚼号:舉狗拼音半: 1选A时的显示结果选择B时的显示结果A111saLB:1010C011000D00000E10110F010G110011H011010I0001J0111K011001000L011001011M10111N11001001000P1001Q011011R01100100

21、1S0010T0011U1101V00001怦0110011X110001Y011001010Z110000搜狗拼音半:J曲 F: C-n-CYuYaikbinTrte*p- eie请输入要进行编码的字柠串(以#结束)三 Aerty输出编码结果:11101L011:按任青键返回搜狗拼音半:d选c时的显示结果利 F: CH-+CYuTanl)inTTt e>p exeI 7:01100101032: 110000 请输入编码(以牡结朿):-klooooooii#7T按任胃键亟回搜狗拼音半:六、心得体会通过这次课程设计,让我对一个程序的数据结构有更全面更进一步的认识,根据不同的需求,采用不同

22、的数据存储方式,不一定要用栈,二叉树等高级类型,有时用基本的一维数组,只要运用得当,也能达到相同的效果,甚至更佳,就如这 次的课程设计, 通过用 for 的多重循环, 舍弃多余的循环, 提高了程序的运行效 率。在编写这个程序的过程中, 我复习了之前学的基本语法, 哈弗曼树最小路径 的求取,哈弗曼编码及译码的应用围, 程序结构算法等一系列的问题它使我对数 据结构改变了看法。 在这次设计过程中, 体现出自己单独设计模具的能力以及综 合运用知识的能力, 体会了学以致用、 突出自己劳动成果的喜悦心情, 也从中发 现自己平时学习的不足和薄弱环节,从而加以弥补。七、参考文献1 徐孝凯编著,数据结构课程实验

23、 ,清华大学出版 2002 年第一版2 乃笑编著,数据结构与算法,电子工业 2004 年 10 月3 严蔚敏 数据结构(C语言版)清华大学附录:源程序如下:#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 MAXS

24、IZE 100typedef struct结点值 权值 双亲结点左孩子结点右孩子结点存放哈夫曼码从 start 开始读 cd 中的哈夫曼码char data;/int weight;/int parent;/int lchild;/int rchild;/HTNode;typedef structchar cdN; / int start; /HCode;void CreateHT(HTNode ht,int n) int i,k,lnode,rnode;/调用输入的数组 ht, 和节点数 nint min1,min2;所有结点的相关域置初值for (i=0;i<2*n-1;i+)hti

25、.parent=hti.lchild=hti.rchild=-1; /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=hti.parent;/根据哈夫曼树求哈夫曼编码while (f!=-1)if (htf.lchild=c)/循序直到树根结点结束循环/处理左孩子结点hc.cdhc.start-='0'else/处理右孩子结点hc.cdhc.start-='1'for (i=n;i<2*n-1;i+)m

26、in1=min2=32767; lnode=rnode=-1;/int/lnodefor (k=0;k<=i-1;k+)if (htk.parent=-1) /找if (htk.weight<min1)/min2=min1;rnode=lnode; min1=htk.weight;lnode=k;else if (htk.weight<min2)min2=htk.weight;rnode=k; htlnode.parent=i;htrnode.parent=i; 父节点是 i/构造哈夫曼树的围是 -32768 32767 和 rnode 记录最小权值的两个结点 只在尚未构造二

27、叉树的结点中查 若权值小于最小的左节点的权值hti.weight=htlnode.weight+htrnode.weight; /两个最小节点的父节点权值为两个最小节点权值之和hti.lchild=lnode;hti.rchild=rnode;/父节点的左节点和右节点两个最小节点的c=f;f=htf.parent;指向哈夫曼编码 hc.cd 中最开hc.start+; /start 始字符hcdi=hc;输出哈夫曼编码的列表void DispHCode(HTNode ht,HCode hcd,int n) /int i,k;输出 data 中的所有数据,即 A-Z输出所有 data 中数据的编

28、码printf(" 输出哈夫曼编码 :n");for (i=0;i<n;i+) /printf(" %c:t",hti.data);for (k=hcdi.start;k<=n;k+)/printf("%c",hcdi.cdk);printf("n");编码函数void editHCode(HTNode ht,HCode hcd,int n) /char stringMAXSIZE;把要进行编码的字符串存入 string为终止标志int i,j,k;scanf("%s",string

29、); /数组中printf("n 输出编码结果 :n");for (i=0;stringi!='#'i+) /#for (j=0;j<n;j+)循环查找与输入字符相同的编if(stringi=htj.data) / 号,相同的就输出这个字符的编码for (k=hcdj.start;k<=n;k+) printf("%c",hcdj.cdk);输出完成后跳出当前 for 循环 break; /void deHCode(HTNode ht,HCode hcd,int n) /char codeMAXSIZE;int i,j,l,k

30、,m,x;scanf("%s",code); / 组中while(code0!='#')for (i=0;i<n;i+)m=0; /mfor (k=hcdi.start,j=0;k<=n;k+,j+) /j 个数if(codej=hcdi.cdk) / m+;if(m=j) / 符串个数相等时则输出这个的 data 数据 printf("%c",hti.data); for(x=0;codex-1!='#'x+) / 字符串删除codex=codex+j;译码函数把要进行译码的字符串存入 code 数为想同编码

31、个数的计数器为记录所存储这个字符的编码当有相同编码时m值加1当输入的字符串与所存储的编码字把已经使用过的 code 数组里的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' / 初始化intfnum=,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 htM;/建立结构体HCode hcdN;/建立结构体for

温馨提示

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

评论

0/150

提交评论