哈弗曼编译码器 (罗忠霖)
哈夫曼编码译码器
沈阳航空航天大学课程设计报告课程设计名称:数据结构课程设计课程设计题目:哈夫曼编码/译码器院(系):计算机学院专业:计算机科学与技术班级:学号:姓名:指导教师:沈阳航空航天大学课程设计报告目录沈阳航空航天大学 (I)第1章概要设计 (1)1.1题目的内容与要求 (1)1.2总体结构 (1)第2章算法分析 (2)2.1核心算法思想 (2)2.2算法结构定义 (2)第3章详细设计 (3)3.1功能流程 (3)第4章系统实现 (5)4.1错误分析 (5)4.2运行结果 (5)参考文献 (8)附录 (9)沈阳航空航天大学课程设计报告第1章概要设计1.1题目的内容与要求内容:设计一个利用哈夫曼算法的编码和译码系统,可以接收从键盘输入的字符集大小、字符和权值信息,创建哈夫曼树生成哈夫曼编码并能对其进行解码。
要求:1.存储结构自定;2.将生成的哈夫曼编码与等长编码进行比较,判断优劣;3.给出动态演示过程(选作)。
1.2总体结构本程序主要分为3个模块(功能模块图见图1.1):主模块,编码模块,译码模块。
主模块:程序的主体部分,分别调用各个模块,实现各项功能。
编码模块:对每个出现的字符进行编码。
译码模块:将已有编码译成字符,使之可以直接被读出。
图1.1功能模块图沈阳航空航天大学课程设计报告第2章算法分析2.1核心算法思想哈夫曼树的建立由赫夫曼算法的定义可知,初始森林中共有n棵只含有根结点的二叉树。
算法的第二步是:将当前森林中的两棵根结点权值最小的二叉树,合并成一棵新的二叉树;每合并一次,森林中就减少一棵树,产生一个新结点。
显然要进行n-1次合并,所以共产生n-1个新结点,它们都是具有两个孩子的分支结点。
由此可知,最终求得的哈夫曼树中一共有2n-1个结点,其中n个结点是初始森林的n个孤立结点。
并且哈夫曼树中没有度数为1的分支结点。
我们可以利用一个大小为2n--1的一维数组来存储哈夫曼树中的结点。
哈夫曼编码是可变字长编码。
哈夫曼编码和译码
哈夫曼树的构造算法: 哈夫曼树的构造算法: 个结点的一维数组, (1)初始化哈夫曼树的 )初始化哈夫曼树的2n-1个结点的一维数组, 个结点的一维数组 即将各结点中的各个域均置0; 即将各结点中的各个域均置 ; 个权值存放到一维数组的前n个单元中 (2)读入 个权值存放到一维数组的前 个单元中, )读入n个权值存放到一维数组的前 个单元中, 它们即为初始森林中的n个只含根结点的权值 个只含根结点的权值; 它们即为初始森林中的 个只含根结点的权值; (3)对森林中的二叉树进行合并,产生 个新 )对森林中的二叉树进行合并,产生n-1个新 结点,依次存放到一维数组的第n+1个开始的单元中, 个开始的单元中, 结点,依次存放到一维数组的第 个开始的单元中 在这个过程中要注意对每个结点双亲域, 在这个过程中要注意对每个结点双亲域,左右孩子 域以及权值的修改. 域以及权值的修改.
13
s1=maxval;s2= maxval;/ 设maxval为float类型最大值 ; ;/*设 ;/ 为 类型最大值 */ for(j =1;j<=i;j+ +) ( ; ; ) if (ht[j].parent = =0) /*判断是否为根结点 判断是否为根结点*/ 判断是否为根结点 if (ht[j].weight<s1) { s2=s1;s1= ht[j].weight; p2=p1;p1=j; } ; ; ; ; else if (ht[j].weight <s2) { s2= ht[j].weight; p2=j; } ; ; ht[p1].parent=i;ht[p2].parent=i; ; ; ht[i].lchild =p1;ht[i].rchild=p2; ; ; ht[i].weight= ht[pl].weight+ht[p2].weight; ; } return (ht);} ;
哈夫曼编码译码器数据结构C语言模板
一、需求分析目前,进行快速远距离通信的主要手段是电报,即将需传送的文字转化成由二级制的字符组成的字符串。
例如,假设需传送的电文为“ABACCDA ”,它只有4种字符,只需两个字符的串,便可以分辨。
假设A 、B 、C 、D 、的编码分别为00,01,10和11,则上述7个字符的电文便为“00010010101100”,总长14位,对方接受时,可按二位一分进行译码。
当然,在传送电文时,希望总长尽可能地短。
如果对每个字符设计长度不等的编码,且让电文中出现次数较多的字符采用尽可能短的编码,则传送电文的总长便可减少。
如果设计A 、B 、C 、D 的编码分别为0,00,1,01,则上述7个字符的电文可转换成总长为9的字符串“000011010”。
但是,这样的电文无法翻译,例如传送过去的字符串中前4个字符的字串“0000”就可以有很多种译法,或是“AAAA ”或者“BB ”,或者“ABA ”等。
因此,若要设计长短不等的编码,则必须是任一字符的编码都不是另一个字符的编码的前缀,这种编码称作前缀编码。
然而,如何进行前缀编码就是利用哈夫曼树来做,也就有了现在的哈夫曼编码和译码。
二、概要设计利用哈夫曼树编/译码 (一)、建立哈夫曼树 (二)、对哈夫曼树进行编码 (三)、输出对应字符的编码 (四)、译码过程主要代码实现: struct code //结构体的定义 { char a; int w; int parent; int lchild; int rchild; };void creation(code *p,int n,int m); //建立哈夫曼树 void coding(code *p,int n); //编码 void display(code *p,int n,int m); //输出函数 void translate(char **hc,code *p,int n); //译码三、 详细设计(一)、建立哈夫曼树a b c d1 2 3 4 5 * * * 6 7 a b * c *ab*c *d * 序号: 字符: 权值: 1 2 3 4 3 6 10 a b * 1 2 1 2 3 3 1 2 3 3 6 4 103 6 图3-1 图3-2 图3-3(二)、对哈夫曼树进行编码 主要代码实现:for(c=i,f=p[i].parent;f!=0;c=f,f=p[f].parent) { if(p[f].lchild==c) //左孩子编码为'0'{ cd[--start]='0'; } else //右孩子编码为'1'{ cd[--start]='1'; } }(三)、输出对应字符的码字符 编码 a 110 b 111 c 10 d(四)、译码过程 主要代码实现:if(strcmp(a,hc[i])==0) //比较两个字符串是否相等,相等则输出0 { for(c=2*n-1,j=0;a[j]!='\0';j++) //从根出发,按字符'0'或'1'确定找左孩子或右孩子 { if(a[j]=='0') //左孩子 {c=p[c].lchild;}else {c=p[c].rchild; //右孩子 }}ab* c* d*1 1 0 1 0 图3-4表3-1从叶子到根逆向求编码a b*c *d *0 1 1 1 从跟到叶子顺向求字符 图3-5四、 调试分析(一)、数字的输入判断(二)、字母的输入判断(三)、程序是否继续进行的判断五、 用户手册(一)、首先根据提示输入初始化数据,提示输入一个数字,请输入一个数a ,0<a<9999;提示输入一个字母,则请输入一个字母(a~z)或者(A~Z)中的一个字符;请勿在输入一个数字后再输入一个字符,或者在输入一个字符后再输入一个数字。
哈夫曼编码译码器1
滁州学院课程设计报告课程名称:数据结构设计题目:哈夫曼编码译码器系计算机科学与技术别专业:网络工程组别:第十组起止日期:2011 年4月28日〜2011 年5月23指导教师:计算机科学与技术系2010年制课程设计任务书目录课程设计的目的和意义。
需求分析。
oooooooooo系统(项目)设计。
CD设计思路及方案。
D2模块的设计及介绍。
D3主要模块程序流程图。
系统实现。
ooooooooooooooD1主调函数。
o ooooooooooD2建立HuffmanTree 。
D3生成HuffmanTree 。
,。
D4电文译码。
o oooooooooooooooooooooooooooooooooooooooooooooooooooo 10小结。
o ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo 136 系统调试。
oooooooooooooooooooooooooooooooooooooooooooooooooooooooo 13参考文献。
oooooooooooooooooooooooooooooooooooooooooooooooooooooooooo 13附录源程序。
oooooooooooooooooooooooooooooooooooooooooooooooooooooo 131.课程设计的目的和意义随着人民生活水平的提高,科学的进步和通信技术的发展。
人们在进行通信的同时要求做到信息交流的保密性和快速准确性,尤其是在军事和高端科技方面。
为了解决上面所提出的问题、实现该目的,设计出了一种快速可靠的编码方式,即哈夫曼编码。
哈夫曼编码的应用很广泛,利用哈夫曼树求得的用于通信的二进制编码称为哈夫曼编码。
树中从根到每个叶子都有一条路径,对路径的各分支约定:指制定左子树的分支表示“ 0” 码,指向右子树的分支表示“ 1”码,去每条路径的“ 0”或“ 1”的序列作为和各个对应的字符编码,这就是哈夫曼树编码。
哈夫曼编译码器
摘要随着计算机的普遍应用与日益发展,其应用早已不局限于简单的数值运算,而涉及到问题的分析,数据结构框架的设计以及设计最短路线等复杂的非数值处理和操作。
算法与数据结构的学习就是为以后利用计算机资源高效地开发非数值处理的计算机程序打下坚实的理论,方法和技术基础。
利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。
但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接收端将传来的数据进行译码(复原)。
对于双工通信(即可以双向传输信息的信道),每端都需要一个完整的编/译码系统,试设计一个哈夫曼编码系统。
关键词:Huffman编码树;编码;译码AbstractWith the widespread application and the development of computer, its application is not limited to a simple numerical computation, and relates to theproblem analysis, data structure design of the framework for the design and the shortest route of complicated non numerical processing and operation. The algorithm and data structure of learning for the future is the use of computer resources efficiently to develop computer programs non numerical treatment to lay a solid theoretical foundation, methods and techniques.The use of Huffman coding can greatly improve the communication channel utilization, reduce the information transmission time, lower transmission costs.However, this requires the sending end through a coding system for pre encoded data, at the receiving end of data from the decoding (Fu Yuan). Forduplex communication (which can be a two-way channel to transmit information),each side needs a complete encoding / decoding system, try to design a Huffman coding system.Keywords: Huffman coding tree; coding;decoding目录1概述 (1)1.1设计背景 (1)1.2问题分析 (1)1.3设计任务 (2)1.4总体结构 (2)2总体设计 (3)2.1总体设计思想、设计方案的选择 (3)2.1.1最优二叉树(Huffman树) (3)2.1.2构造哈夫曼树的步骤 (3)2.1.3数据结构的选择 (4)2.2结构设计 (4)2.2.1结构体存储表示 (4)2.2.2主函数模块 (4)2.2.3系统结构图 (5)3详细设计........................................... 错误!未定义书签。
哈夫曼编码译码器数据结构C语言
哈夫曼编码译码器数据结构C语言哈夫曼编码译码器数据结构C语言⒈简介本文档旨在介绍一个使用C语言实现的哈夫曼编码译码器的数据结构。
哈夫曼编码是一种用于数据压缩的算法,它通过将频率较高的字符用较短的编码表示,从而实现数据的压缩和解压缩。
⒉哈夫曼编码(Huffman Coding)基本概念⑴字符频率统计在进行哈夫曼编码之前,我们首先需要统计每个字符在待编码的数据中出现的频率。
通过遍历数据,记录每个字符的出现次数,我们可以得到一个字符频率的统计表。
⑵构建哈夫曼树通过字符频率的统计表,我们可以构建一个哈夫曼树。
哈夫曼树是一种二叉树,其中每个叶节点表示一个字符,而每个内部节点表示一个权重,即两个子节点的频率之和。
⑶哈夫曼编码在哈夫曼树构建完成后,我们可以根据树的结构每个字符的编码。
哈夫曼编码的特点是没有任何一个字符的编码是另一个字符编码的前缀,这种编码方式称为前缀编码。
⑷哈夫曼译码根据字符的哈夫曼编码,我们可以将编码后的数据进行解码,还原为原始的数据。
通过遍历哈夫曼树,从根节点开始,根据每个二进制位的取值进行向左或向右的移动,直至叶节点,然后获取该叶节点对应的字符。
⒊数据结构设计⑴结点结构定义一个哈夫曼树的结点结构,包含以下字段:●`char data`:字符●`int frequency`:字符的频率●`int is_leaf`:是否为叶节点●`struct Node left_child`:左子节点●`struct Node right_child`:右子节点⑵频率统计表使用一个数组或链表来记录每个字符的频率统计信息,包含以下字段:●`char data`:字符●`int frequency`:字符的频率⑶编码表使用一个数组或链表来记录每个字符的哈夫曼编码,包含以下字段:●`char data`:字符●`char code`:编码⒋算法流程⑴字符频率统计算法步骤:⒈初始化频率统计表为空。
⒉读取待编码的数据。
数据库实验哈夫曼编译码器
汇报人:XX
目录
添加目录标题
01
哈夫曼编译码器原理
02
数据库实验哈夫曼编译码 器实现
03
数据库实验哈夫曼编译码 器应用场景
04
数据库实验哈夫曼编译码 器与其他编译码器的比较
05
数据库实验哈夫曼编译码 器的发展趋势和未来展望
06
添加章节标题
哈夫曼编译码器 原理
哈夫曼编码原理
感谢您的观看
汇报人:XX
与算术编译码的比较
编码方式:哈夫曼编码采用可变长 度编码,而算术编码采用固定长度 编码
编码效率:哈夫曼编码通常比算术 编码更高效,因为它可以更好地利 用数据分布信息
精度:算术编码具有更高的精度, 因为它可以将概率估计精确到小数 点后多位
适用场景:哈夫曼编码适用于数据 量较小且概率分布不均的情况,而 算术编码适用于数据量较大且概率 分布均匀的情况
哈夫曼编码算法的改进方向
优化编码效率:提高哈夫曼编码的压缩比和编码速度 动态调整编码表:根据数据特征自适应调整哈夫曼编码表 降低误码率:改进哈夫曼编码的解码算法,降低解码错误率 跨平台兼容性:提高哈夫曼编码在不同平台和环境下的兼容性和稳定性
哈夫曼编码与其他技术的结合应用
哈夫曼编码与 压缩技术结合: 提高数据压缩
效率
哈夫曼编码与 加密技术结合: 增强数据传输
安全性
哈夫曼编码与 云计算技术结 合:实现大规
模数据处理
哈夫曼编码与 人工智能技术 结合:优化算 法提高编码效
率
哈夫曼编码在物联网和云计算领域的应用前景
物联网中的数据传输:哈夫曼编码能够有效地压缩数据,降低传输成本和提高传输效率,尤其在物联网领 域中,对于大量数据的处理和传输具有重要意义。
哈夫曼编码译码器实验报告
哈夫曼编码译码器实验报告实验名称:哈夫曼编码译码器实验一、实验目的:1.了解哈夫曼编码的原理和应用。
2.实现一个哈夫曼编码的编码和译码器。
3.掌握哈夫曼编码的编码和译码过程。
二、实验原理:哈夫曼编码是一种常用的可变长度编码,用于将字符映射到二进制编码。
根据字符出现的频率,建立一个哈夫曼树,出现频率高的字符编码短,出现频率低的字符编码长。
编码过程中,根据已建立的哈夫曼树,将字符替换为对应的二进制编码。
译码过程中,根据已建立的哈夫曼树,将二进制编码替换为对应的字符。
三、实验步骤:1.构建一个哈夫曼树,根据字符出现的频率排序。
频率高的字符在左子树,频率低的字符在右子树。
2.根据建立的哈夫曼树,生成字符对应的编码表,包括字符和对应的二进制编码。
3.输入一个字符串,根据编码表将字符串编码为二进制序列。
4.输入一个二进制序列,根据编码表将二进制序列译码为字符串。
5.比较编码前后字符串的内容,确保译码正确性。
四、实验结果:1.构建哈夫曼树:-字符出现频率:A(2),B(5),C(1),D(3),E(1) -构建的哈夫曼树如下:12/\/\69/\/\3345/\/\/\/\ABCDE2.生成编码表:-A:00-B:01-C:100-D:101-E:1103.编码过程:4.译码过程:5.比较编码前后字符串的内容,结果正确。
五、实验总结:通过本次实验,我了解了哈夫曼编码的原理和应用,并且实现了一个简单的哈夫曼编码的编码和译码器。
在实验过程中,我充分运用了数据结构中的树的知识,构建了一个哈夫曼树,并生成了编码表。
通过编码和译码过程,我进一步巩固了对树的遍历和节点查找的理解。
实验结果表明,本次哈夫曼编码的编码和译码过程正确无误。
在实验的过程中,我发现哈夫曼编码对于频率较高的字符具有较短的编码,从而实现了对字符串的高效压缩。
同时,哈夫曼编码还可以应用于数据传输和存储中,提高数据的传输效率和存储空间的利用率。
通过本次实验,我不仅掌握了哈夫曼编码的编码和译码过程,还深入了解了其实现原理和应用场景,加深了对数据结构和算法的理解和应用能力。
哈夫曼编译码器_
《数据结构》课程设计目录1. 问题描述……………………………………………第 2页2. 系统设计……………………………………………第 2页3. 数据结构与算法描述………………………………第 5页4. 测试结果与分析……………………………………第 6页5. 总结 (10)6. 参考文献 (10)附录程序源代码 (11)课程设计题目1. 问题描述利用哈夫曼编码进行信息通信可大大提高信道利用率,缩短信息传输时间,降低传输成本。
要求在发送端通过一个编码系统对待传数据预先编码;在接收端将传来的数据进行译码(复原)。
对于双工信道(既可以双向传输信息的信道),每端都需要一个完整的编/译码系统。
试为这样的信息收发站写一个哈夫曼的编/译码系统。
2.1基本要求一个完整的系统应具有以下功能:1)I:初始化(Initialization)。
从终端读入字符集大小n,以及n个字符和n个权值,建立哈夫曼树,并将它存于文件hfmTree中。
输出哈夫曼树,及各字符对应的编码。
2)W:输入(Input)。
从终端读入需要编码的字符串s,将字符串s存入文件Tobetran.txt中。
3)E:编码(Encoding)与译码(Decoding)。
编码(Encoding)。
利用已建好的哈夫曼树(如不在内存,则从文件htmTree中读入),对文件ToBeTran中的正文进行编码,然后将结果存入文件CodeFile中。
译码(Decoding)。
利用已建好的哈夫曼树将文件CodeFile中的代码进行译码,结果存入文件TextFile中。
打印代码文件(Print)。
将文件CodeFile以紧凑格式显示在终端上,每行50个代码。
同时将此字符形式的编码写入文件CodePrint中。
4)T:打印哈夫曼树(Tree Printing)。
将已在内存中的哈夫曼树以直观的方式(树或凹入表形式)显示在终端上,同时将此字符形式的哈夫曼树写入文件TreePrint中。
5)Q:退出程序。
哈夫曼编码译码器1
哈夫曼编码/译码器1.设计目的《数据结构》课程主要介绍最常用的数据结构,阐明各种数据结构内在的逻辑关系,讨论其在计算机中的存储表示,以及在其上进行各种运算时的实现算法,并对算法的效率进行简单的分析和讨论。
进行数据结构课程设计要达到以下目的:1了解并掌握数据结构与算法的设计方法,具备初步的独立分析和设计能力;2初步掌握软件开发过程的问题分析、系统设计、程序编码、测试等基本方法和技能;3提高综合运用所学的理论知识和方法独立分析和解决问题的能力;训练用系统的观点和软件开发一般规范进行软件开发,培养软件工作者所应具备的科学的工作方法和作风。
2.设计内容和要求设计内容:设计一个利用哈夫曼算法的编码和译码系统,重复地显示并处理以下项目,直到选择退出为止。
(1) 将权值数据存放在数据文件(文件名为data.txt,位于当前目录中);(2) 分别采用动态和静态存储结构; 初始化:键盘输入字符集大小n、n个字符和n个权值,建立哈夫曼树;(3) 编码:利用建好的哈夫曼树生成哈夫曼编码;输出编码;设计要求:(1) 符合课题要求,实现相应功能;(2) 要求界面友好美观,操作方便易行;(3) 注意程序的实用性、安全性。
3.本设计所采用的数据结构(1)二叉树的链式存储结构typedef struct BTNode{ ElemType data ;struct BTNode *Lchild , *Rchild , *parent ;}BTNode;(2)先序遍历二叉树(3)哈夫曼树的构造(4)进行哈夫曼编码的基本过程4.功能模块详细设计4.1 详细设计思想(1)该程序利用了二叉树的链式存储结构(三叉链表结点),其定义了四个域:一个数据域,两个分别指向左右子结点的指针域,以及一个指向其双亲结点的指针域,typedef struct BTNode{ ElemType data ;struct BTNode *Lchild , *Rchild , *parent ;}BTNode;(2)Huffman树的构造①根据n个权值{w1, w2,…,wn},构造成n棵二叉树的集合F={T1, T2,…,Tn},其中每棵二叉树只有一个权值为wi的根结点,没有左、右子树;②在F中选取两棵根结点权值最小的树作为左、右子树构造一棵新的二叉树,且新的二叉树根结点权值为其左、右子树根结点的权值之和;③在F中删除这两棵树,同时将新得到的树加入F中;④重复②、③,直到F只含一颗树为止。
数据结构课程设计哈夫曼编码译码器
题目一: 哈夫曼编码与译码一、任务设计一个运用哈夫曼算法的编码和译码系统, 反复地显示并解决以下项目, 直到选择退出为止。
规定:1) 将权值数据存放在数据文献(文献名为data.txt, 位于执行程序的当前目录中) ;2) 初始化:键盘输入字符集记录字符权值、自定义26个字符和26个权值、记录文献中一篇英文文章中26个字母, 建立哈夫曼树;3) 编码: 运用建好的哈夫曼树生成哈夫曼编码;4) 输出编码(一方面实现屏幕输出, 然后实现文献输出);5)译码(键盘接受编码进行译码、文献读入编码进行译码);6) 界面优化设计。
二、流程图三、代码分解 //头文献 #include<stdio.h> #include<string.h> #include<stdlib.h> #include <conio.h> #define N 1000 #define M 2*N-1 #define MAXcode 6000 //函数声明void count(CHar &ch,HTNode ht[]);void editHCode(HTNode ht[],HCode hcd[],CHar &ch,int n,char bianma[]); //编码函数void printyima(HTNode ht[],HCode hcd[],int n,char bianma[]); //译码函数 void creatHT(HTNode ht[],int n);字符集记录符集记录权值 权值 至文献“哈夫曼树。
t xt” 菜单1.从键盘输入字符集进行编码2.从文献读入字符集进行编码1.从键盘输入编码进行译码2.从文献读入编码进行译码0.返回上级菜单 0.返回上级菜单void CreateHCode (HTNode ht[],HCode hcd[],int n);void DispHCode(HTNode ht[],HCode hcd[],int n);void input_key(CHar &ch);void input_file(CHar &ch);void input_cw(HTNode ht[]);void bianma1(HTNode ht[],HCode hcd[],CHar &ch,int n,char bianma[]); void bianma2(HTNode ht[],HCode hcd[],CHar &ch,int n,char bianma[]); void yima1(HTNode ht[],HCode hcd[],int n,char bianma[]);void yima2(HTNode ht[],HCode hcd[],int n,char bianma[]);void creat_cw();void bianmacaidan();void yimacaidan();void bianmayima();int caidan();//结构体typedef struct{char data;int parent;int weight;int lchild;int rchild;}HTNode;typedef struct{char cd[N];int start;}HCode;typedef struct{char s[N];int num;}CHar;CHar ch;HTNode ht[M];HCode hcd[N];//主函数int main(){int xh;while(1){system("color 1f"); //操作菜单背景颜色 xh=caidan(); //调用菜单函数switch(xh) //switch语句 {case 1:system("cls");creat_cw();break;case 2:system("cls");creatHT(ht,n);break;case 3:system("cls");CreateHCode(ht,hcd,n);DispHCode(ht,hcd,n);break;case 4:system("cls");bianmayima();break;case 0:system("cls");printf("\n\n\n\n\n\n\n\n\n\t\t\t\t感谢使用本系统!\n\n\n\n\n\n\n \t\t\t");exit(0);default:system("cls");putchar('\a');printf("\n\t\t输入有误, 请重新输入:\n");break;}}return 0;}//菜单函数int caidan() //菜单函数模块//{int xh;printf("\n\n\n");printf("\t\t 欢迎使用哈夫曼编码译码系统\n");printf("\t\t \n");printf("\t\t*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*\n");printf("\t\t*= =*\n");printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*= =*\n");printf("\t\t*= 1.建立字符权值=*\n");printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*= =*\n"); printf("\t\t*= 2.建立并输出哈夫曼树=*\n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*= =*\n"); printf("\t\t*= 3.生成并查看哈夫曼编码=*\n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*= =*\n"); printf("\t\t*= 4.编码与译码=*\n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*= =*\n"); printf("\t\t*= 0.退出系统=*\n"); printf("\t\t*= =*\n"); printf("\t\t*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*\n"); printf("\n\t\t请输入序号进行选择:");scanf("%d", &xh);return xh; //返回从键盘接受的选项}void bianmayima(){int xh;while(1){printf("\n\n\n\n\n");printf("\t\t 编码与译码\n"); printf("\t\t \n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n");printf("\t\t*= 1.编码=*\n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n"); printf("\t\t*= 2.译码=*\n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n"); printf("\t\t*= 0.返回上级菜单=*\n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n"); printf("\n\t\t请输入序号进行选择:");scanf("%d",&xh);switch(xh) //switch语句{case 1:system("cls");bianmacaidan();break;case 2:system("cls");yimacaidan();break;case 0:system("cls");return;default:system("cls");putchar('\a');printf("\n\t\t输入有误, 请重新输入:\n");break;}}}void yimacaidan(){int xh;while(1){printf("\n\n\n\n\n");printf("\t\t 译码\n"); printf("\t\t \n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n"); printf("\t\t*= 1.键盘输入编码进行译码=*\n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n"); printf("\t\t*= 2.文献读入编码进行译码=*\n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n"); printf("\t\t*= 0.返回上级菜单=*\n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n"); printf("\n\t\t请输入序号进行选择:");scanf("%d",&xh);switch(xh) //switch语句{case 1:system("cls");yima1(ht,hcd,n,bianma);break;case 2:system("cls");yima2(ht,hcd,n,bianma);break;case 0:system("cls");return;default:system("cls");putchar('\a');printf("\n\t\t输入有误, 请重新输入:\n");break;}}}void bianmacaidan(){int xh;while(1){printf("\n\n\n\n\n");printf("\t\t 编码\n"); printf("\t\t \n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n"); printf("\t\t*= 1.键盘输入字符集编码=*\n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n"); printf("\t\t*= 2.文献读入文章编码=*\n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n"); printf("\t\t*= 0.返回上级菜单=*\n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n"); printf("\n\t\t请输入序号进行选择:");scanf("%d",&xh);switch(xh) //switch语句{case 1:system("cls");bianma1(ht,hcd,ch,n,bianma);break;case 2:system("cls");bianma2(ht,hcd,ch,n,bianma);break;case 0:system("cls");return;default:system("cls");putchar('\a');printf("\n\t\t输入有误, 请重新输入:\n");break;}}}void creat_cw(){int xh2;while(1){printf("\n\n\n\n\n");printf("\t\t 建立字符权值\n"); printf("\t\t \n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n"); printf("\t\t*= 1.从键盘输入字符集进行记录=*\n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n"); printf("\t\t*= 2.从文献读入字符集记录=*\n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n"); printf("\t\t*= 3.自定义字符权值=*\n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n"); printf("\t\t*= 0.返回上级菜单=*\n"); printf("\t\t*= *=*=*=*=*=*=*=*=*=*=*=*=*=*=* =*\n"); printf("\n\t\t请输入序号进行选择:");scanf("%d",&xh2);switch(xh2) //switch语句{case 1:system("cls");input_key(ch);break;case 2:system("cls");input_file(ch);break;case 3:system("cls");input_cw(ht);break;case 0:system("cls");return;default:system("cls");putchar('\a');printf("\n\t\t输入有误, 请重新输入:\n");break;}}}//建立字符权值模块void input_key(CHar &ch){int i,j=0;char st[N];printf("请输入字符集(以‘#’结束):\n");for(i=0;i<N;i++){scanf("%c",&st[i]);if(st[i]=='#'){st[i]='\0';break;}}strcpy(ch.s,st);count(ch,ht);printf("按任意键返回!");getch();system("cls");return;}void input_file(CHar &ch){int i;FILE*fp;char filename[20];printf("请输入要打开的文献名(*.txt):");scanf("%s",&filename);if((fp=fopen(filename,"r"))==NULL){printf("\n\t\t文献打开失败");return;}for(i=0;!feof(fp);i++){fread(&ch.s[i],sizeof(char),1,fp);}printf("读入成功!\n");printf("文献中的字符集为:%s\n",ch.s);fclose(fp);count(ch,ht);printf("按任意键返回!");getch();system("cls");return;}void input_cw(HTNode ht[]){int i,w,s,j;char a;printf("要输入的字符总个数是?:");scanf("%d",&s);n=s;printf("请输入字符及其权值:\n");for(i=0;i<s;i++){printf("请输入第%d个字母:",i+1);scanf("%s",&a);ht[i].data=a;printf("请输入其权值:");scanf("%d",&w);ht[i].weight=w;}FILE *fp;if((fp=fopen("data.txt","w"))==0){printf("\n\t\t文献打开失败");return;}printf("\n定义权值成功!\n\n");printf("各字符及其权值为:\n\n");fprintf(fp,"各字符及其权值为:\n");printf(" 字符\t权值");fprintf(fp," 字符\t权值");for(j=0;j<i;j++){ printf("\n");fprintf(fp,"\n");printf(" %-8c%-8d",ht[j].data,ht[j].weight);fprintf(fp," %-8c%-8d%",ht[j].data,ht[j].weight); }printf("\n");printf("\n字符权值已输出至文献“data.txt”!");fclose(fp);printf("输入完毕, 按任意键返回!");getch();system("cls");return;}//记录字符权值函数void count(CHar &ch,HTNode ht[]){int i,j,m=0;char c[N];int sum[N]={0};for(i=0;ch.s[i]!='\0';i++){for(j=0;j<m;j++)if(ch.s[i]==c[j]||(c[j]>='a'&&c[j]<='z'&&ch.s[i]+32==c[j])) break;if(j<m)sum[j]++;else{if(ch.s[i]>='A'&&ch.s[i]<='Z')c[j]=ch.s[i]+32;else c[j]=ch.s[i];sum[j]++;m++;}}for(i=0;i<m;i++){ht[i].data=c[i];ht[i].weight=sum[i];}n=m;FILE *fp;if((fp=fopen("data.txt","w"))==0) {printf("\n\t\t文献打开失败"); return;}printf("\n记录权值成功!\n\n"); printf("各字符及其权值为:\n\n"); fprintf(fp,"各字符及其权值为:\n"); printf(" 字符\t权值");fprintf(fp," 字符\t权值");for(j=0;j<m;j++){ printf("\n");fprintf(fp,"\n");printf(" %-8c%-8d",ht[j].data,ht[j].weight);fprintf(fp," %-8c%-8d%",ht[j].data,ht[j].weight);}printf("\n");printf("\n字符权值已输出至文献“data.txt”!");fclose(fp);}//构造哈夫曼树void creatHT(HTNode ht[],int n){FILE *fp;if((fp=fopen("哈夫曼树.txt","w"))==0){printf("\n\t\t文献打开失败");return;}int i,j,k,lnode,rnode;int min1,min2;for (i=0;i<2*n-1;i++)ht[i].parent=ht[i].lchild=ht[i].rchild=-1;for (i=n;i<2*n-1;i++){min1=min2=32767;lnode=rnode=-1;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;ht[i].weight=ht[lnode].weight+ht[rnode].weight;ht[i].lchild=lnode;ht[i].rchild=rnode;}printf("建立huffman树成功!\n");printf("输出huffman树:\n");fprintf(fp,"输出huffman树:\n");printf("\t字符\t权值\t父节点\t 左子节点\t右子节点");fprintf(fp,"\t字符\t权值\t父节点\t 左子节点\t右子节点");for(j=1;j<i;j++){ printf("\n");fprintf(fp,"\n");printf("\t %-8c%-8d%-10d%-14d%-10d",ht[j].data,ht[j].weight,ht[j].parent,ht[i]. lchild,ht[j].rchild);fprintf(fp,"\t %-8c%-8d%-10d%-14d%-10d",ht[j].data,ht[j].weight,ht[j].parent,h t[i].lchild,ht[j].rchild);}printf("\n");printf("哈夫曼树已输出至文献“哈夫曼树.txt”!按任意键返回!");fclose(fp);getch();system("cls");return;}//生成哈夫曼编码void CreateHCode (HTNode ht[],HCode hcd[],int n){int i,f,c,j=0;HCode hc;for(i=0;i<n;i++){hc.start=n;c=i;hc.cd[hc.start--]='0';f=ht[i].parent;while(f!=-1){if (ht[f].lchild==c)hc.cd[hc.start--]='0';elsehc.cd[hc.start--]='1';c=f;f=ht[f].parent;}hc.start++;for(j=0;j<hc.start;j++)hc.cd[j]=' ';hcd[i]=hc;}}void DispHCode(HTNode ht[],HCode hcd[],int n) {FILE *fp;if((fp=fopen("哈夫曼编码.txt","w"))==0){printf("\n\t\t文献打开失败");return;}int i,k;int sum=0,m=0,j;printf("输出字符哈夫曼编码:\n"); fputs("输出字符哈夫曼编码:\n",fp); for (i=0;i<n;i++){j=0;printf("%c:\t",ht[i].data);fprintf(fp,"\n%c:\t",ht[i].data);for (k=hcd[i].start;k<=n;k++){printf("%c",hcd[i].cd[k]);j++;fprintf(fp,"%c",hcd[i].cd[k]); }m+=ht[i].weight;sum+=ht[i].weight*j;printf("\n");}printf("\n哈夫曼编码已保存至文献“哈夫曼编码.txt!按任意键返回!”");fclose(fp);getch();system("cls");}//编码函数void bianma1(HTNode ht[],HCode hcd[],CHar &ch,int n,char bianma[]){int i;char str[N];printf("请输入要编码的字符集(以‘#’结束):\n");for(i=0;i<N;i++){scanf("%c",&str[i]);if(str[i]=='#'){str[i]='\0';break;}}strcpy(ch.s,str);ch.num=strlen(str);editHCode(ht,hcd,ch,n,bianma);getch();system("cls");}void bianma2(HTNode ht[],HCode hcd[],CHar &ch,int n,char bianma[]) {int i;FILE*fp;char filename[20];printf("请输入要打开的文献名(*.txt):");scanf("%s",&filename);if((fp=fopen(filename,"r"))==NULL){printf("\n\t\t文献打开失败");return;}for(i=0;!feof(fp);i++){fread(&ch.s[i],sizeof(char),1,fp);}ch.num=strlen(ch.s);printf("\n读入成功!\n");printf("文献中的字符集为:\n%s",ch.s);fclose(fp);editHCode(ht,hcd,ch,n,bianma);system("cls");return;}//译码函数void yima1(HTNode ht[],HCode hcd[],int n,char bianma[]) {int i;char code[MAXcode];printf("请输入编码进行译码(以‘#’结束):\n");for(i=0;i<MAXcode;i++){scanf("%c",&code[i]);if(code[i]=='#'){code[i]='\0';break;}}strcpy(bianma,code);printyima(ht,hcd,n,bianma);printf("\n译码完毕!按任意键返回!");getch();system("cls");return;}void yima2(HTNode ht[],HCode hcd[],int n,char bianma[]) {int i;FILE*fp;char filename[20];printf("请输入要打开的文献名(*.txt):");scanf("%s",&filename);if((fp=fopen(filename,"r"))==NULL){printf("\n\t\t文献打开失败");return;}for(i=0;!feof(fp);i++){fread(&bianma[i],sizeof(char),1,fp);}printf("读入成功!\n");printf("文献中的编码是:%s\n",bianma);printyima(ht,hcd,n,bianma);printf("\n译码完毕!按任意键返回!");getch();system("cls");}四、调试结果主菜单建立字符权值选择2.从文献读入字符进行记录输入测试文献名“cs.txt”输出个字符权值建立哈夫曼树并输出至文献生成哈夫曼编码并保存至文献编码选择2.从文献读入字符集编码编码结果保存至文献译码选择2.从文献读入编码, 读入上一步的编码译码完毕, 返回!退出系统。
哈夫曼码编、译码器的实现
综合实验四哈夫曼码编、译码器的实现一、实验名称哈夫曼码编、译码器的实现二、实验目的1、熟练哈夫曼树的定义,掌握构造哈夫曼树的方法。
2、掌握哈夫曼编码和译码方法。
3、掌握文本文件的读写方法。
三、实验内容1、实验内容:利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。
但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接收端将传来的数据进行译码。
对于双工信道(即可以双向传输信息的信道),每端都需要一个完整的编码、译码系统。
试为这样的信息收发站写一个哈夫曼码的编码、译码系统。
一个完整的系统应以下功能:(1) 从终端读入字符集大小n,以及n个字符和n个权值,建立哈夫曼树,并将它存放在文件hfmTree中。
(2) 利用已建立好的哈夫曼树(如不在内存,则从文件hfmTree中读入),对文件ToBeTran中的正文进行编码,然后将结果代码存(传输)到文件CodeFile中.(3) 译码(Decoding)。
利用已建好的哈夫曼树,对传输到达的CodeFile中的数据代码进行译码,将译码结果存入文件TextFile。
(4) 将文件CodeFile以紧凑格式显示在终端上,每行50个代码。
同时将此字符形式的编码文件写入文件CodePrin中。
(5) 打印印哈夫曼树(TreePrinting)。
将已在内存中的哈夫曼树以直观的方式(树或凹入表的形式)显示在终端上,同时将此字符形式的哈夫曼树写入文件TreePrint中。
(6)数据结构设计根据下面给出的存储结构定义typedef struct // 定义哈夫曼树中每个结点结构体类型{char ch; //结点字符信息int weight; // 定义一个整型权值变量int lchild; // 定义左、右孩子及双亲指针int rchild;int parent;} HTNode;typedef HTNode HFMT[MAXLEN]; //用户自定义HFMT数组类型typedef char** HfCode;//动态分配字符数组存储哈夫曼编码表(7)基本操作的函数设计void InitHFMT(HFMT T);//初始化哈夫曼树void InputWeight(HFMT T,char* weightFile);// 输入权值void SelectMin(HFMT T,int i,int *p1,int *p2);//选择所有结点中较小的结点void CreatHFMT(HFMT T);// 构造哈夫曼树,T[2*n-1]为其根结点void PrintHFMT (HFMT T);// 输出向量状态表void printHfCode(HfCode hc);//输出字符的哈夫曼编码序列HfCode hfEnCoding(HFMT T);//利用构成的哈夫曼树生成字符的编码void print_HuffmanTree(HFMT HT,int t,int i)//按树形形态输出哈夫曼树的形态void Encoder(char* original,char* codeFile,HfCode hc,HFMT HT);//利用已建好的哈夫曼树,对original文件中要传输的原始数据进行编码,//将编码结果存入文件codeFile中void Decoder(char* codeFile ,char* textFile,HFMT HT);//利用已建好的哈夫曼树,对传输到达的codeFile中的数据代码进行译码,//将译码结果存入文件textFile中2、实验要求(1)、用C语言编程实现上述实验内容中的结构定义和算法。
哈夫曼编码译码器数据结构C语言
哈夫曼编码译码器数据结构C语言哈夫曼编码译码器数据结构C语言文档1.引言本文档介绍了一个基于哈夫曼编码的译码器的设计和实现。
哈夫曼编码是一种无损压缩算法,通过对出现频率较高的符号进行较短的编码,来减小数据的存储或传输所需的空间。
2.哈夫曼编码原理在哈夫曼编码中,使用一颗二叉树,将出现频率较高的符号表示为树的较浅的节点,而出现频率较低的符号表示为树的较深的节点。
通过遍历整个二叉树,可以得到每个符号对应的哈夫曼编码。
2.1 创建哈夫曼树首先,根据每个符号的出现频率,创建一颗包含所有符号的节点的最小堆。
然后,根据最小堆的特性,每次从最小堆中选取两个出现频率最低的节点,并合并为一个新节点。
重复这个过程,直到最小堆中只剩下一个节点,即哈夫曼树的根节点。
2.2 哈夫曼编码通过遍历哈夫曼树,可以得到每个符号对应的哈夫曼编码。
在遍历的过程中,左孩子表示编码中的“0”,右孩子表示编码中的“1”。
每次左移一个位,表示向左遍历,每次右移一个位,表示向右遍历。
3.数据结构设计下面介绍了本文档中所使用的各种数据结构和相关函数的设计。
3.1 结构定义```cstruct Node {char symbol。
int frequency。
struct Node leftChild。
struct Node rightChild。
}。
```3.2 方法定义```c// 创建哈夫曼树struct Node createHuffmanTree(char symbols, int frequencies, int size)// 哈夫曼编码表void generateHuffmanTable(struct Node root, char huffmanTable, char currentCode)// 哈夫曼编码char encode(char data, char huffmanTable)// 哈夫曼译码char decode(char encodedData, struct Node root)```4.实现细节在这个章节中,我们将会具体讨论各个方法的实现细节和使用示例。
哈夫曼编码译码器数据结构C语言
哈夫曼编码译码器数据结构C语言哈夫曼编码译码器数据结构C语言引言哈夫曼编码是一种用于无损数据压缩的编码方式,它利用出现频率较高的字符使用较短的编码,而出现频率较低的字符使用较长的编码。
通过这种方式可以使得编码后的数据占据较少的存储空间。
本文将介绍如何使用C语言实现一个哈夫曼编码译码器的数据结构。
哈夫曼树哈夫曼树是哈夫曼编码的关键数据结构,它可以通过给定的字符频率构建出一棵树。
在哈夫曼树中,每个字符都有一个对应的叶子节点,而非叶子节点表示编码的中间过程。
具体构建哈夫曼树的步骤如下:1. 统计每个字符的出现频率。
2. 将每个字符及其频率构建成一个节点,并按照频率从小到大排序。
3. 从频率最小的两个节点开始,合并成一个新节点,并将新节点的频率设为两个节点频率之和。
4. 将新节点插入到节点列表中,保持节点列表有序。
5. 重复步骤3和步骤4,直到只剩下一个节点,这个节点就是哈夫曼树的根节点。
编码在构建了哈夫曼树之后,我们可以根据树的结构来进行编码。
对于每个字符,其编码是由根节点到对应叶子节点路径上的边来表示的。
具体编码的步骤如下:1. 从根节点开始,递归遍历哈夫曼树的每个节点。
2. 如果当前节点为叶子节点,记录下从根节点到该叶子节点所经过的路径上的边的取值(0表示左边,1表示右边),得到该字符的编码。
3. 对于每个字符,将其编码存储起来以便后续使用。
译码译码的过程与编码相反,我们可以根据编码来找到对应的字符。
具体译码的步骤如下:1. 从哈夫曼树的根节点开始,逐个读取待译码的数据。
2. 如果读取的数据为0,移动到左子节点;如果读取的数据为1,移动到右子节点。
3. 如果移动到了叶子节点,记录下该叶子节点对应的字符,并回到根节点。
4. 重复步骤2和步骤3,直到读取完毕所有的数据,得到原始的字符序列。
实现下面是一个用C语言实现的哈夫曼编码译码器的数据结构示例:```cinclude <stdio.h>typedef struct Node {char character;int frequency;struct Node left;struct Node right;} Node;typedef struct HuffmanTree {Node root;} HuffmanTree;HuffmanTree buildHuffmanTree(char characters, int frequencies, int size) {// 构建哈夫曼树的代码实现}void encode(HuffmanTree tree, char string, char encodedString) {// 编码的代码实现}void decode(HuffmanTree tree, char encodedString, char decodedString) {// 译码的代码实现}int mn() {// 测试代码}```总结通过本文,我们了解了哈夫曼编码译码器的数据结构及其在C 语言中的实现。
哈夫曼编码译码器数据结构C语言
哈夫曼编码译码器数据结构c语言哈夫曼编码译码器数据结构目录1.引言1.背景2.目的3.范围2.哈夫曼编码概述1.哈夫曼树2.哈夫曼编码3.哈夫曼译码3.数据结构设计1.哈夫曼树结构2.编码表结构3.输入数据结构4.输出数据结构4.算法实现1.哈夫曼树构建算法2.编码表算法3.哈夫曼编码算法4.哈夫曼译码算法5.使用示例1.编码示例2.译码示例6.性能分析1.时间复杂度分析2.空间复杂度分析7.风险和限制1.输入数据限制2.输出数据限制3.算法限制8.附录1.示例代码2.测试数据3.参考文献1.引言1.1 背景哈夫曼编码是一种经典的数据压缩算法,通过构建哈夫曼树,将输入的数据进行编码。
哈夫曼编码的特点是可变长度编码,频率高的字符使用短编码,频率低的字符使用长编码。
1.2 目的本文档旨在详细介绍哈夫曼编码译码器的数据结构设计和算法实现,帮助读者理解和使用该编码器。
1.3 范围本文档涵盖了哈夫曼编码和译码的概述,数据结构设计,算法实现,使用示例以及性能分析。
2.哈夫曼编码概述2.1 哈夫曼树哈夫曼树是一种特殊的二叉树,用于构建哈夫曼编码。
它通过合并两个最小频率的节点来构建树,直到所有节点都被合并。
2.2 哈夫曼编码哈夫曼编码是将字符映射为可变长度的二进制码。
频率高的字符使用短码,频率低的字符使用长码。
编码表中保存了每个字符对应的编码。
2.3 哈夫曼译码哈夫曼译码是根据哈夫曼编码,将二进制码转换为原始字符。
3.数据结构设计3.1 哈夫曼树结构哈夫曼树的结构包含一个根节点和左右子节点。
```ctypedef struct huffmanTreeNode {char data; // 节点字符数据int frequency; // 节点字符出现的频率struct huffmanTreeNode left; // 左子节点指针struct huffmanTreeNode right; // 右子节点指针} huffmanTreeNode;```3.2 编码表结构编码表结构用于保存字符和对应编码的映射关系。
实验三、哈夫曼编译码器
实验三、哈夫曼编/译码器一、需求分析(说明实验的任务,包括输入、输出、功能、测试数据等)任务:利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。
但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接受端将传来的数据进行译码(复原)。
对于双工信道(即可以双向传输信息的信道),每端都需要一个完整的编/译码系统。
试为这样的信息收发站写一个哈夫曼编/译码系统。
功能要求:(1) 初始化(readdata)。
从终端读入字符集大小n,以及n个字符和n个权值。
(2) 建立哈夫曼树(createhuff)。
根据n个字符和n个权值建立哈夫曼树,并可以将建好的哈夫曼树显示在终端上。
(3) 编码(encoding)。
利用已建好的哈夫曼树,对输入(或文件file1.txt 中)的正文进行编码,然后将结果在终端输出(或存入文件file2.txt)。
(4) 译码(decoding)。
利用已建好的哈夫曼树将内存(或文件file2.txt)中的代码进行译码,结果在终端输出(或存入文件file3.txt)。
测试数据用下表给出的字符集和频度的实际统计数据建立哈夫曼树,并实现以下报文的编码和译码:“hello world”、“data structure with c”算法设计思想:设w存放n个字符和n个权值,可用顺序存储结构(也可用链式存储结构)ht 存储哈夫曼树,用hc存储n个字符的哈夫曼编码。
根据w中存放的数据,可以用课本上的算法建立哈夫曼树,也可用其他的方法建立哈夫曼树;对于编码,可以对已建立的哈夫曼树,求出n个字符的编码,存放于hc,这过程可以从每一叶子结点开始到根结点的顺序来生成。
然后,对要编码的报文根据hc中的码表进行编码并输出(也可存于一文件);对于译码,可以根据输入(或从文件读入)的代码,根据哈夫曼树来译码,其方法是,从哈夫曼树的根结点开始,碰到为‘0’的代码转向左孩子,碰到‘1’的代码转向右孩子,直至叶子结点,该叶子结点的有关数据就是一个所要译的码,这样重复进行,到代码译完为止。
数据结构课程设计哈夫曼编码译码器
数据结构课程设计哈夫曼编码译码器个节点的权值、父节点、左孩子和右孩子,然后通过选择最小的两个节点合并,构建Huffman树;3:Huffman编码:通过遍历Huffman树,对每个叶子节点进行编码,将编码结果存入新的文件中;4:译码:读取存放Huffman编码的文件,通过遍历Huffman树进行译码,将译码结果存入新的文件中;5:结果验证:比较原文件和译码结果文件的内容是否一致,输出结果;3.函数说明1:CrtHuffmanTree():创建Huffman树;2:HuffmanCoding():对Huffman树进行遍历,生成Huffman编码;3:HuffmanDecoding():对Huffman编码进行译码,生成原文件内容;4:CompareFile():比较原文件和译码结果文件的内容是否一致;五、详细设计1.统计字符频率:定义结构体typedef struct strchar data;char num;str;其中data域存放字符名称,num域存放字符出现频率,读取文件ywq1.txt,通过循环比较将结果赋入S2[128]中;2.创建Huffman树:定义结构体typedef structchar data;int weight;int parent;int lchild;int rchild;HTNode,HuffmanTree[M+1];作为Huffman树存储节点类型,调用CrtHuffmanTree()函数,初始化各个节点的权值、父节点、左孩子和右孩子,然后通过选择最小的两个节点合并,构建Huffman树;3.Huffman编码:通过遍历Huffman树,对每个叶子节点进行编码,将编码结果存入新的文件中;4.译码:读取存放Huffman编码的文件,通过遍历Huffman树进行译码,将译码结果存入新的文件中;5.结果验证:比较原文件和译码结果文件的内容是否一致,输出结果;六、测试1.测试数据测试文件:ywq1.txt(包含英文字母、数字和符号)2.测试结果测试结果正确,能够正确地对文件进行Huffman编码和译码,生成的译码结果文件与原文件内容一致;七、总结通过本次课程设计,我深入了解了Huffman编码/译码器的实现原理和过程,掌握了Huffman树的创建、存储和遍历方法,提高了动手能力,同时也为数据压缩问题提供了一种有效的解决方法。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
《数据结构》实验报告题目: 实验五 哈夫曼编/译码器 学号:2010810072 成 绩班级: 计算1013 日期:2011.11.15 姓名:罗忠霖 指导老师:杨艳华一、实验目的:本次的实验目的在于使读者深入了解树的特性,以便在实际问题背景下灵活运用他们;同时还将巩固掌握对树结构的构造方法的理解,并且回顾文件操作的使用。
二、实验环境:本次试验在VC++环境下调试。
三、实验内容与完成情况:1.问题描述利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输的时间,降低传输成本。
但是这要求在发送端通过一个编码系统对待传数据预先编码,在接收端将传来的数据进行译码。
对于双工信道,每端都需要一个完整的编/译码系统。
试为这样的信息收发站写一个哈夫曼码的编/译码系统。
2.基本要求一个完整的系统应具有以下功能:(1) 初始化,构造哈弗曼树。
(2) 编码。
(3) 译码。
(4) 印代码文件。
(5) 印哈弗曼树。
3.程序代码#include<stdio.h> #include<stdlib.h> #include<string.h> #include<conio.h> typedef struct { char chr1; int weight; int parent,lchild,rchild; }HTNode,*HuffmanTree; typedef struct { char chr; int w1; char *code;//编码}Ch;//字符和对应的权值及编码void Select(HuffmanTree &HT1,int j,int &s1,int &s2);void HuffmanCoding(HuffmanTree &HT, Ch *w, int n);//构造哈夫曼树HTvoid encoding(HuffmanTree &HT, Ch *ch, int n);//求每个字符的哈夫曼编码void Encoding(Ch *ch1, int n);//编码void Decoding(HuffmanTree &HT,int sum);//译码void caidan();void Printf();void main(){FILE *p;int choice,n1,w2=1;int i,flag=1,m;char ch;HuffmanTree HTr;Ch *c;caidan();while(flag){loop: printf("\n*请选择(0-5):");scanf("%d",&choice);switch(choice){case 1:printf("请输入字符集大小n=");scanf("%d",&n1);c=(Ch *)malloc((n1+1)*sizeof(Ch));flushall();for(i=1;i<=n1;i++){printf("请输入字符及其权值:");scanf("%c%d",&ch,&w2);c[i].chr=ch;c[i].w1=w2;flushall();}HuffmanCoding(HTr,c,n1);encoding(HTr,c,n1);break;case 2:Encoding(c,n1);break;case 3:Decoding(HTr,n1);break;case 4:Printf();break;case 5: m=2*n1-1;if((p=fopen("TreePrint.txt","w"))==NULL)printf("File could not be opened\n");else{fprintf(p,"\n哈夫曼树的构造如下所示:\n");fprintf(p," 结点weight parent lchild rchild");for (i=1; i<=m; i++){fprintf(p,"\n%4d%8d%8d%8d%8d",i,HTr[i].weight,HTr[i].parent,HTr[i].lchild, HTr[i].rchild);}}fclose(p);printf("\n哈夫曼树的构造如下所示:\n");printf(" 结点weight parent lchild rchild");for(i=1; i<=m; i++){printf("\n%4d%8d%8d%8d%8d",i,HTr[i].weight,HTr[i].parent,HTr[i].lchild, HTr[i].rchild);}break;case 0: flag=0;printf("你选择了推出程序,欢迎使用!\n");break;default:goto loop;}}}void caidan(){ printf("\n*****************哈夫曼编译器*****************\n");printf(" 1.初始化\n");printf(" 2.编码\n");printf(" 3.译码\n");printf(" 4.打印代码文件\n");printf(" 5.打印哈夫曼树\n");printf(" 6.退出系统\n");printf("**********************************************\n");}void Select(HuffmanTree &HT1,int j,int &s1,int &s2){//在HT[1...j]中选择parent为0且weight最小的两个结点,其序号分别为s1和s2int i=0,d=0,h;for(i=j;i>=0;i--){if(HT1[i].parent!=0) //在双亲不为0的条件下continue;if(d==0) //用s1记录第一个双亲为0的元素所在的位置{s1=i;d++;}else if(d==1) //用s2记录第而个双亲为0的元素所在的位置{s2=i;d++;}else if(d==2){if(HT1[s1].weight<=HT1[s2].weight ) //s2用于存储最小值的位置{h=s1;s1=s2;s2=h;}if(HT1[i].weight<HT1[s1].weight ) //s1用于存放次小值的位置s1=i;}}}void HuffmanCoding(HuffmanTree &HT, Ch *w, int n){// *w存放n个字符的权值(均>0),构造哈夫曼树HTFILE *p;int i, j, m, s1, s2;if (n<=1) return;m = 2 * n - 1;//树的结点总数HT = (HuffmanTree)malloc((m+1) * sizeof(HTNode)); // 0号单元未用for (i=1; i<=n; i++){ //初始化HT[i].chr1=w[i].chr;HT[i].weight=w[i].w1;//HT[i].parent=0;HT[i].lchild=0;HT[i].rchild=0;}for (i=n+1; i<=m; i++){ //初始化HT[i].weight=0;HT[i].parent=0;HT[i].lchild=0;HT[i].rchild=0;}for (i=n+1; i<=m; i++)// 建哈夫曼树{// 在HT[1...i-1]中选择parent为0且weight最小的两个结点,其序号分别为s1和s2。
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;}if((p=fopen("hfmTree.txt","w"))==NULL)printf("File could not be opened\n");else{fprintf(p,"\n哈夫曼树的构造如下所示:\n");fprintf(p," 结点weight parent lchild rchild");for (i=1; i<=m; i++){fprintf(p,"\n%4d%8d%8d%8d%8d",i,HT[i].weight,HT[i].parent,HT[i].lchild, HT[i].rchild);}}fclose(p);}void encoding(HuffmanTree &HT, Ch *ch, int n){ //--- 从叶子到根逆向求每个字符的哈夫曼编码---int i,c,f,start;//char *cd;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';else cd[--start] = '1';}ch[i].code = (char *)malloc((n-start)*sizeof(char)); // 为第i个字符编码分配空间strcpy(ch[i].code, &cd[start]); // 从cd复制编码(串)到code}free(cd); // 释放工作空间}void Encoding(Ch *ch1, int n)//利用已经建立的哈弗曼树编码对输入的字符进行哈弗曼编码{FILE *q1,*q2;//char a[100]; //用于存放输入的字符char num[1000],c;char *p=num; //用于存放字符对应的哈弗曼编码int i,j;if((q1=fopen("ToBeTran.txt","r"))==NULL)printf("File could not be opened\n");else{rewind(q1);while(!feof(q1)) //依次判断字符的对应的哈弗曼编码{c=fgetc(q1);for(j=1;j<=n;j++){if(c==ch1[j].chr){printf("%c:%s ",ch1[j].chr,ch1[j].code);strcpy(p,ch1[j].code);p=p+strlen(ch1[j].code);break;}//如果找到就把对应的哈弗曼编码复制到字符数组num中}}*p='\0';printf("\n得到的编码是:\n");for(i=0;num[i]!='\0';i++) //输出字符对应的哈弗曼编码{if(i==50) printf("\n"); //当输出50个字符时,进行换行printf("%c",num[i]);}printf("\n");}fclose(q1);if((q2=fopen("CodeFile.txt","w"))==NULL)printf("File could not be opened\n");else{i=0;while(num[i]!='\0'){if(i==50) fprintf(q2,"\n");fprintf(q2,"%c",num[i++]);}fprintf(q2,"\n");}fclose(q2);}void Decoding(HuffmanTree &HT,int sum) //译码{FILE *p;//char code1[1000]; //用于存放输入的密码char a1[100],c; //用于存放翻译好的字符int n=0,i=0,b=2*sum-1;if((p=fopen("CodeFile.txt","r+"))==NULL)printf("File could not be opened\n");else{while(!feof(p)){c=fgetc(p);if(c=='0') b=HT[b].lchild; //当遇到0时指向哈弗曼树的左子树if(c=='1') b=HT[b].rchild; //当遇到1时指向哈弗曼树的右子树if(HT[b].lchild==0&&HT[b].rchild==0) //当左右子树均为空时表明已找到对应的字符{a1[n++]=HT[b].chr1;b=2*sum-1; //将对应的字符放在数组a1中,并重新设置b的值继续翻译}}a1[n]='\0';i=0;while(a1[i]!='\0') //输出翻译好的字符{if(i==50) printf("\n");printf("%c",a1[i++]);}printf("\n");}fclose(p);if((p=fopen("TextFile.txt","w"))==NULL)printf("File could not be opened\n");else{i=0;fprintf(p,"得到的翻译结果是:\n");while(a1[i]!='\0'){if(i==50) fprintf(p,"\n");fprintf(p,"%c",a1[i++]);}fprintf(p,"\n");}fclose(p);}void Printf(){FILE*p;if((p=fopen("CodeFile.txt","r"))==NULL)printf("File could not be opened\n");else{printf("得到的编码是:\n");while(!feof(p)){int i=0;if(i==50) printf("\n"); //当输出50个字符时,进行换行printf("%c",fgetc(p));i++;}printf("\n");}fclose(p);}4.结果显示:四、实验小结及体会:通过本实验能够更好掌握文件指针的操作运用,加深理解,运用它解决一些实际问题,且能教熟练掌握数的结构以及哈弗曼算法。