版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、数据结构课程设计 题目:哈夫曼编码译码 专业:通信工程 学号: 指导教师:吴泽晖 目录 目录 1 一、需求分析 2 二、设计要求 2 三、概要设计 2 1、 流程图 2 2、 设计包含的几个部分 4 四、详细设计 2 五、显示结果 9. 六、心得体会 10 七、参考文献 11 哈夫曼编码译码 一、 需求分析 在当今信息爆炸时代, 如何采用有效的数据压缩技术节省数据文件的存储空 间和计算机网络的传送时间已越来越引起人们的重视, 赫夫曼编码正是一种应用 广泛且非常有效的数据压缩技术。 哈夫曼编码是一种编码方式, 以哈夫曼树即 最优二叉树, 带权路径长度最小的二叉树, 经常应用于数据压缩。 哈弗曼编
2、码使 用一特殊的编码表将源字符 (例如某文件中的一个符号) 进行编码。 这编码表的 特殊之处在于, 它是根据每一个源字符出现的估算概率而建立起来的 (出现概率 高的字符使用较短的编码, 反之出现概率低的则使用较长的编码, 这便使编码之 后的字符串的平均期望长度降低,从而达到无损压缩数据的目的) 。赫夫曼编码 的应用很广泛, 利用赫夫曼树求得的用于通信的二进制编码称为赫夫曼编码。 树 中从根到每个叶子都有一条路径, 对路径上的各分支约定: 指向左子树的分支表 示“ 0”码,指向右子树的分支表示“ 1”码,取每条路径上的“ 0”或“ 1”的序 列作为和各个叶子对应的字符的编码, 这就是赫夫曼编码。
3、 哈弗曼译码输入字符 串可以把它编译成二进制代码,输入二进制代码时可以编译成字符串。 二、 设计要求 对输入的一串电文字符实现赫夫曼编码, 再对赫夫曼编码生成的代码串进行 译码,输出电文字符串。 通常我们把数据压缩的过程称为编码, 解压缩的过程称 为解码。电报通信是传递文字的二进制码形式的字符串。 但在信息传递时, 总希 望总长度能尽可能短,即采用最短码。假设每种字符在电文中出现的次数为Wi, 编码长度为Li,电文中有n种字符,则电文编码总长度为刀 WiLi。若将此对应 到二叉树上,Wi为叶结点的权,Li为根结点到叶结点的路径长度。那么,刀WiLi 恰好为二叉树上带权路径长度。因此 ,设计电文
4、总长最短的二进制前缀编码, 就是以 n 种字符出现的频率作权, 构造一棵赫夫曼树, 此构造过程称为赫夫曼编 码。设计实现的功能: (1) 赫夫曼树的建立; (2) 赫夫曼编码的生成; (3) 编 码文件的译码。 三、 概要设计 哈夫曼编 译码器的主要功能是先建立哈夫曼树,然后利用建好的哈夫曼树 生成哈夫曼编码后进行译码 。 在数据通信中,经常需要将传送的文字转换成由二进制字符 0、1 组成的二 进制串,称之为编码。构造一棵哈夫曼树,规定哈夫曼树中的左分之代表 0,右 分支代表 1,则从根节点到每个叶子节点所经过的路径分支组成的 0和 1的序列 便为该节点对应字符的编码,称之为哈夫曼编码。 最简
5、单的二进制编码方式是等长编码。 若采用不等长编码, 让出现频率高的 字符具有较短的编码, 让出现频率低的字符具有较长的编码, 这样可能缩短传送 电文的总长度。哈夫曼树课用于构造使电文的编码总长最短的编码方案。 (1)其主要流程图如图 1-1 所示。 开始 是 结点数是否大于1 l2*N? 是 输出根结点和权值 将data和权值赋给ht 调用SELECT函数 计算根结点函数 父结点为两子结点之和 是否为根结点? 是 左子是否为空? 否 否 是否为空 输出两子结点和已构造的结点 此时编码为0 编码为1 结束 (2)设计包含的几个方面: 赫夫曼树的建立 赫夫曼树的建立由赫夫曼算法的定义可知, 初始森
6、林中共有 n 棵只含有根结点的 二叉树。算法的第二步是: 将当前森林中的两棵根结点权值最小的二叉树, 合并 成一棵新的二叉树;每合并一次,森林中就减少一棵树,产生一个新结点。显然 要进行 n1 次合并,所以共产生 n1 个新结点,它们都是具有两个孩子的分支 结点。由此可知,最终求得的赫夫曼树中一共有2n1个结点,其中n个结点是 初始森林的 n 个孤立结点。 并且赫夫曼树中没有度数为 1 的分支结点。 我们可以 利用一个大小为 2n-1 的一维数组来存储赫夫曼树中的结点。 赫夫曼编码 要求电文的赫夫曼编码, 必须先定义赫夫曼编码类型, 根据设计要求和实际需要 定义的类型如下: typedet s
7、truct char ch; / 存放编码的字符 char bitsN 1; /存放编码位串 int len; / 编码的长度 CodeNode; / 编码结构体类型 代码文件的译码 译码的基本思想是: 读文件中编码, 并与原先生成的赫夫曼编码表比较, 遇到相 等时,即取出其对应的字符存入一个新串中。 四、详细设计 (1)赫夫曼树的存储结构描述为: #define N 50 /叶子结点数 #define M 2*N-1 /赫夫曼树中结点总数 typedef struct int weight; / 叶子结点的权值 int lchild, rchild, parent; / 左右孩子及双亲指针
8、HTNode; / 树中结点类型 typedef HTNode HuffmanTreeM+1; 哈弗曼树的算法 void CreateHT(HTNode ht,int n) / int i,k,lnode,rnode; int min1,min2; for (i=0;i2*n-1;i+) hti.parent=hti.lchild=hti.rchild=-1; / -1 for (i=n;i2*n-1;i+)/ min1=min2=32767; /int lnode=rnode=-1;/lnode 调用输入的数组 ht, 和节点数 n 所有结点的相关域置初值 构造哈夫曼树 的围是 -32768
9、 32767 和 rnode 记录最小权值的两个结点 位置 for (k=0;k=i-1;k+) 只在尚未构造二叉树的结点中查 若权值小于最小的左节点的权值 if (htk.parent=-1) / 找 if (htk.weightmin1)/ min2=min1;rnode=lnode; min1=htk.weight;lnode=k; else if (htk.weightmin2) min2=htk.weight;rnode=k; 两个最小节点的 / 两个最小节点的 父节点的左节点 htlnode.parent=i;htrnode.parent=i; / 父节点是 i hti.weigh
10、t=htlnode.weight+htrnode.weight; 父节点权值为两个最小节点权值之和 hti.lchild=lnode;hti.rchild=rnode; / 和右节点 (2)哈弗曼编码 void CreateHCode(HTNode ht,HCode hcd,int n) int i,f,c; HCode hc; for (i=0;in;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=h
11、tf.parent; hc.start+; /start 根据哈夫曼树求哈夫曼编码 循序直到树根结点结束循环 处理左孩子结点 处理右孩子结点 指向哈夫曼编码 hc.cd 中最开 始字符 hcdi=hc; void DispHCode(HTNode ht,HCode hcd,int n) / int i,k; printf( 输出哈夫曼编码 :n); for (i=0;in;i+) / printf( %c:t,hti.data); for (k=hcdi.start;k=n;k+)/ printf(%c,hcdi.cdk); printf(n); void editHCode(HTNode h
12、t,HCode hcd,int n) / char stringMAXSIZE; int i,j,k; scanf(%s,string); / 数组中 printf(n 输出编码结果 :n); for (i=0;stringi!=#;i+) /# for (j=0;jn;j+) if(stringi=htj.data) / 号,相同的就输出这个字符的编码 for (k=hcdj.start;k=n;k+) 输出哈夫曼编码的列表 输出 data 中的所有数据,即 A-Z 输出所有 data 中数据的编码 编码函数 把要进行编码的字符串存入 string 为终止标志 循环查找与输入字符相同的编 p
13、rintf(%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;in;i+) m=0; /m for (k=hcdi.start,j=0;k=n;k+,j+) /j 个数 if(codej=hcdi.cdk) / m+; if(m=j) / 符串个数相等时则输出这个的 data 数据 printf(%c,h
14、ti.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; 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=,64,13,22,32,103
15、,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;in;i+) / 把初始化的数据存入 ht 结构体中 hti.data=stri; hti.weight=fnumi; while (flag) / 菜单函数,当 flag 为 0 时跳出循环 ( 5)显示部分源程序: printf(n); printf( * ); 显示编码 *) 进行编码 *) 进行译码 *) 退出 *n); printf(n* 1 printf(n*
16、 2 printf(n* 3 printf(n* 4 printf( * * ); printf(n); printf( 请输入选择的编号 :); scanf(%c, 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( 请输入要进行编码的字符串 ( 以#结束 ):
17、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); 五、调试结果 进入主菜单 I 小 F; C+CTnTaii1b
18、3LnTwi:exa BSD1 耳車耳*上卓承*冀# -*-+ J*-4 Jlj|l 4lj|l 4uj|l 4lj|l 4沖事齐卓齐車齐卓#木克 A =+ H 显示编码+ -p exe I 7:0110010103 2: 110000 请输入编码(以牡结朿):- klooooooii# 7T 按任胃键亟回 搜狗拼音半: 六、心得体会 通过这次课程设计,让我对一个程序的数据结构有更全面更进一步的认识,根据 不同的需求,采用不同的数据存储方式,不一定要用栈,二叉树等高级类型,有时用基本的一维数组,只要运用得当,也能达到相同的效果,甚至更佳,就如这 次的课程设计, 通过用 for 的多重循环, 舍
19、弃多余的循环, 提高了程序的运行效 率。在编写这个程序的过程中, 我复习了之前学的基本语法, 哈弗曼树最小路径 的求取,哈弗曼编码及译码的应用围, 程序结构算法等一系列的问题它使我对数 据结构改变了看法。 在这次设计过程中, 体现出自己单独设计模具的能力以及综 合运用知识的能力, 体会了学以致用、 突出自己劳动成果的喜悦心情, 也从中发 现自己平时学习的不足和薄弱环节,从而加以弥补。 七、参考文献 1 徐孝凯编著,数据结构课程实验 ,清华大学出版 2002 年第一版 2 乃笑编著,数据结构与算法,电子工业 2004 年 10 月 3 严蔚敏 数据结构 (C语言版)清华大学 附录: 源程序如下:
20、 #include #include / 要用 system 函数要调用的头文件 #include / 用 getch() 要调用的头文件 #include #define N 50 / 义用 N 表示 50 叶节点数 #define M 2*N-1 / 用 M 表示节点总数 当叶节点数位 n 时总节点数为 2n-1 #define MAXSIZE 100 typedef struct 结点值 权值 双亲结点 左孩子结点 右孩子结点 存放哈夫曼码 从 start 开始读 cd 中的哈夫曼码 char data;/ int weight;/ int parent;/ int lchild;/ i
21、nt rchild;/ HTNode; typedef struct char cdN; / int start; / HCode; void CreateHT(HTNode ht,int n) int i,k,lnode,rnode; / 调用输入的数组 ht, 和节点数 n int min1,min2; 所有结点的相关域置初值 for (i=0;i2*n-1;i+) hti.parent=hti.lchild=hti.rchild=-1; / void CreateHCode(HTNode ht,HCode hcd,int n) int i,f,c; HCode hc; for (i=0;
22、in;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;i2*n-1;i+) min1=min2=32767; lnode=rnode=-1; / /int /lnode for (k=0;k=i-1;k+) if (htk.parent=-1) / 找 if (htk.weightmin1)/ min2=min1;
23、rnode=lnode; min1=htk.weight;lnode=k; else if (htk.weightmin2) min2=htk.weight;rnode=k; htlnode.parent=i;htrnode.parent=i; 父节点是 i / 构造哈夫曼树 的围是 -32768 32767 和 rnode 记录最小权值的两个结点 只在尚未构造二叉树的结点中查 若权值小于最小的左节点的权值 hti.weight=htlnode.weight+htrnode.weight; / 两个最小节点的 父节点权值为两个最小节点权值之和 hti.lchild=lnode;hti.rchi
24、ld=rnode; / 父节点的左节点 和右节点 两个最小节点的 c=f;f=htf.parent; 指向哈夫曼编码 hc.cd 中最开 hc.start+; /start 始字符 hcdi=hc; 输出哈夫曼编码的列表 void DispHCode(HTNode ht,HCode hcd,int n) / int i,k; printf( 输出哈夫曼编码 :n); 输出 data 中的所有数据,即 A-Z 输出所有 data 中数据的编码 for (i=0;in;i+) / printf( %c:t,hti.data); for (k=hcdi.start;k=n;k+)/ printf(%
25、c,hcdi.cdk); printf(n); 编码函数 void editHCode(HTNode ht,HCode hcd,int n) / char stringMAXSIZE; int i,j,k; 把要进行编码的字符串存入 string 为终止标志 scanf(%s,string); / 数组中 printf(n 输出编码结果 :n); for (i=0;stringi!=#;i+) /# for (j=0;jn;j+) 循环查找与输入字符相同的编 if(stringi=htj.data) / 号,相同的就输出这个字符的编码 for (k=hcdj.start;k=n;k+) pri
26、ntf(%c,hcdj.cdk); 输出完成后跳出当前 for 循环 break; / 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;in;i+) m=0; /m for (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 数 为想同编码个数的计数器 为记录所存储这个字符的编码 当有相同编码时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
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026年集运站安全培训内容实操要点
- 2026年宾馆全员安全培训内容核心要点
- 植树节环保公益宣传方案
- 铜陵市铜陵县2025-2026学年第二学期六年级语文第五单元测试卷部编版含答案
- 玉溪市峨山彝族自治县2025-2026学年第二学期六年级语文第五单元测试卷部编版含答案
- 吉安市吉安县2025-2026学年第二学期六年级语文第五单元测试卷部编版含答案
- 聊城市临清市2025-2026学年第二学期六年级语文第五单元测试卷部编版含答案
- 邵阳市城步苗族自治县2025-2026学年第二学期六年级语文第五单元测试卷部编版含答案
- 酒泉地区安西县2025-2026学年第二学期六年级语文第五单元测试卷部编版含答案
- 漯河市临颍县2025-2026学年第二学期六年级语文第五单元测试卷部编版含答案
- 12《古诗三首》课件-2025-2026学年统编版语文三年级下册
- 团队精神与忠诚度培训讲义
- 2026河南新乡南太行旅游有限公司招聘16岗49人考试参考试题及答案解析
- 2026年辽宁点石联考高三年级3月学情调研语文试卷及答案
- 短剧网络播出要求与规范手册
- 2026年春季西师大版(2024)小学数学三年级下册教学计划含进度表
- 江苏苏锡常镇四市2026届高三下学期教学情况调研(一)数学试题(含答案)
- 2026年3月15日九江市五类人员面试真题及答案解析
- 高顿教育内部考核制度
- 2026年山西工程职业学院单招职业技能考试题库及答案解析
- (2025年)上海专升本普通心理学模拟试题真题试卷及答案
评论
0/150
提交评论