哈夫曼编码和译码系统
哈夫曼编码和译码的设计与实现

算法与数据结构课程设计哈夫曼编码和译码的设计与实现1。
问题描述利用哈夫曼编码进行通信可以大大提高信道的利用率,缩短信息传输时间,降低传输成本。
但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接收端将传来的数据进行译码(复原)。
对于双工信道(即可以双向传输信息的信道),每端都需要一个完整的编/译码系统。
试为这样的信息收发站设计一个哈夫曼码的编/译码系统。
2。
基本要求a。
编/译码系统应具有以下功能:(1)I:初始化(Initialization)。
从终端读入字符集大小n,以及n个字符和n个权值,建立哈夫曼树,并将它存于文件hfmTree中。
(2)E:编码(Encoding).利用已建好的哈夫曼树(如不在内存,则从文件hfmTree中读入),对文件ToBeTran中的正文进行编码,然后将结果存入文件CodeFile中。
(3)D:译码(Decoding)。
利用已建好的哈夫曼树将文件CodeFile中的代码进行译码,结果存入文件TextFile中。
(4)P:印代码文件(Print).将文件CodeFile以紧凑格式显示在终端上,每行50个代码。
同时将此字符形式的编码文件写入文件CodePrin中。
(5)T:印哈夫曼树(Tree printing)。
将已在内存中的哈夫曼树以直观的方式(树或凹入表形式或广义表)显示在终端上,同时将此字符形式的哈夫曼树写入文件TreePrint中.b。
测试数据(1)利用下面这道题中的数据调试程序.某系统在通信联络中只可能出现八种字符,其概率分别为0。
25,0.29,0。
07,0.08,0.14,0。
23,0。
03,0。
11,试设计哈夫曼编码。
(2)用下表给出的字符集和频度的实际统计数据建立哈夫曼树,并实现以下报文的编码和译码:“THIS PROGRAM IS MY FAVORITE".字符空格 A B C D E F G H I J K L M 频度 186 64 13 22 32 103 21 15 47 57 1 5 32 20字符 N O P Q R S T U V W X Y Z频度57 63 15 1 48 51 80 23 8 18 1 16 13.需求分析3。
哈夫曼编码和译码

哈夫曼树的构造算法: 哈夫曼树的构造算法: 个结点的一维数组, (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);} ;
哈夫曼编码和译码

哈夫曼编码和译码哈夫曼编码是一种用于数据压缩的编码方法,通过根据字符出现的频率对字符进行编码,以便能够用较少的位数来表示出现频率较高的字符。
编码过程中,根据频率最低的字符构建一棵哈夫曼树,将字符的编码表示为树的路径。
而哈夫曼译码则是将经过哈夫曼编码后的数据解码成原始数据的过程。
在给定的文本中,首先需要统计每个字符的出现频率。
然后使用这些频率构建哈夫曼树。
构建哈夫曼树的过程中使用最小堆数据结构,通过不断合并两个最小频率的字符节点来构建树。
合并两个节点的过程中,创建一个新的节点来作为它们的父节点,并将其频率设置为两个子节点频率之和。
在构建树的过程中,赋予左子节点编码为0,右子节点编码为1。
构建完成哈夫曼树后,将每个字符的编码表示为从根节点到该字符节点的路径,例如,向左走的路径可以表示为0,向右走的路径可以表示为1。
为了能够正确译码,需要将字符及其对应的编码存储在一个编码表中。
对于给定的文本数据,应用哈夫曼编码后,会得到一个压缩后的编码字符串。
在哈夫曼译码过程中,从根节点开始遍历编码字符串的每一位,如果是0,则向左子节点移动,如果是1,则向右子节点移动,直到到达叶子节点。
找到叶子节点后,将对应的字符输出,并回到根节点,继续下一位的译码,直到编码字符串结束。
哈夫曼编码可以实现无损压缩,即通过译码过程能够还原出原始数据,而不会丢失任何信息。
它是一种广泛应用于数据压缩领域的有效方法,用于减小数据存储和传输的大小。
在实际应用中,哈夫曼编码被广泛应用于图像、音频和视频等多媒体数据的压缩中。
总结起来,哈夫曼编码是一种用于数据压缩的编码方法,通过根据字符出现的频率对字符进行编码,以便用较少的位数来表示出现频率较高的字符。
哈夫曼译码则是将经过编码后的数据解码成原始数据的过程。
它通过构建哈夫曼树和编码表,实现了高效的数据压缩和解压缩。
哈夫曼编码被广泛应用于数据存储和传输领域,特别是在多媒体数据的压缩中。
哈夫曼编码译码系统

《数据结构》课程设计6.5电文的编码和译码姓名: XXX院系: 计算机学院专业: 计算机科学与技术年级: 13级学号: E11314XXX指导教师:XXX2015年10月30 日目录1.课程设计的目的 (3)2.需求分析 (3)3电文的编码和译码的设计 (3)3.1概要设计 (3)3.1.1 主界面设计 (3)3.1.2 存储结构 (4)3.1.3 系统功能设计 (4)3.2详细设计 (4)3.2.1 系统子程序及功能设计 (4)3.2.2 数据类型定义 (6)3.2.3 系统主要子程序详细设计 (7)3.3调试分析 (11)3.4用户手册 (12)4总结 (12)5、程序清单:(见附录) (13)7、程序运行结果 (13)附录1 (18)1.课程设计的目的(1) 熟练使用C 语言编写程序,解决实际问题;(2) 了解并掌握数据结构与算法的设计方法,具备初步的独立分析和设计能力;(3) 初步掌握软件开发过程的问题分析、系统设计、程序编码、测试等基本方法和技能;(4) 提高综合运用所学的理论知识和方法独立分析和解决问题的能力。
2.需求分析(1)为信息收发站写一个哈夫曼编/译码系统。
(2)要求在发送端通过一个编码系统对待传数据预先编码,在接收端将传来的数据进行译码(复原)。
(3)要求可以将哈夫曼树以树状或凹入法打印到屏幕。
3电文的编码和译码的设计3.1概要设计3.1.1 主界面设计图1主界面,如图1所示,包含初始化,编码,译码,代码文件,哈夫曼树五个菜单。
其中,菜单1用来从终端读入n个字符和n个权值,建立哈夫曼树,并将它存于文件中; 菜单2用来利用已建好的哈夫曼树,对文件中或直接输入的正文进行编码,然后将结果存入文件中,如果哈夫曼树不在内存可通过初始化或文件读入到内存;菜单3利用已建好的哈夫曼树将文件中的代码进行译码,译码结果存入文件中,若哈夫曼树不在内存中,处理方式与菜单2相同;菜单4将编码文件以紧凑格式显示在终端上,每行50个代码,同时将此字符形式的编码写入文件中;菜单5将已在内存中的哈夫曼树以凹入法显示在终端上。
哈夫曼编码译码器系统

具体介绍:在本课题中,我们在硬盘E盘中预先建立一个file1.txt文档,在里面编辑一篇文章(大写)。
然后运行程序,调用fileopen()函数读出该文章,显示在界面;再调用jsq()函数对该文章的字符种类进行统计,并对每个字符的出现次数进行统计,并且在界面上显示;然后以每个字符出现次数作为权值,调用ChuffmanTree()函数构建哈夫曼树;并调用print1()和print2()函数将哈夫曼的存储结构的初态和终态进行输出。
然后调用HuffmanEncoding()函数对哈夫曼树进行编码,调用coding()函数将编码写入文件;再调用decode()对编码进行译码,再输出至界面。
至此,整个工作就完成了。
测试数据:例如从文本中读到文章为:IAMASTUDENT。
则效果如下:IAMASTUDENT--------------------------------------HuffmanTree的初态:200010001000100010001000100020001000-000-000-000-000-000-000-000-000--------------------------------------字符A次数:2字符D次数:1字符E次数:1字符I次数:1字符M次数:1字符N次数:1字符S次数:1字符T次数:2字符U次数:1--------------------------------------HuffmanTree的终态:21300110001100011100111001120011200214001130021423215452156731691416810417111271713141101516--------------------------------------译码后的字符串:IAMASTUDENT********************************************************** Press any key to continue文档由风行播放器/暴风影音2014:/整理3系统(项目)设计(1)设计思路及方案本课题是用最优二叉树即哈夫曼树来实现哈夫曼编码译码器的功能。
哈夫曼编码译码系统

《数据结构》课程设计——赫夫曼编码/译码器设计指导教师:孙树森、周维达班级:09数媒(2)班学号:E09700227姓名:曾焕凯数据结构课程设计报告书一、实验目的1、提高分析问题、解决问题的能力,进一步巩固数据结构各种原理与方法。
2、熟悉掌握一门计算机语言,可以进行数据算法的设计。
二、实验原理1、哈夫曼树的定义:假设有n 个权值,试构造一颗有n 个叶子节点的二叉树,每个叶子带权值为wi,其中树带权路径最小的二叉树成为哈夫曼树或者最优二叉树;2、哈夫曼树的构造:weight 为输入的频率数组,把其中的值赋给依次建立的HT Node 对象中的data 属性,即每一个HT Node 对应一个输入的频率。
然后根据data 属性按从小到大顺序排序,每次从data 取出两个最小和此次小的HT Node,将他们的data 相加,构造出新的HTNode 作为他们的父节点,指针parent,leftchild,rightchild 赋相应值。
在把这个新的节点插入最小堆。
按此步骤可以构造构造出一棵哈夫曼树。
通过已经构造出的哈夫曼树,自底向上,由频率节点开始向上寻找parent,直到parent 为树的顶点为止。
这样,根据每次向上搜索后,原节点为父节点的左孩子还是右孩子,来记录1 或0,这样,每个频率都会有一个01 编码与之唯一对应,并且任何编码没有前部分是同其他完整编码一样的。
三、实验步骤先统计要压缩编码的文件中的字符字母出现的次数,按字符字母和空格出现的概率对其进行哈夫曼编码。
然后读入要编码的文件,编码后存入另一个文件;接着再调出编码后的文件,并对其进行译码输出,最后存入另一个文件中。
具体步骤:1.初始化,统计文本文件中各字符的个数作为权值,生成哈夫曼树;2.根据符号概率的大小按由大到小顺序对符号进行排序;3.把概率最小的两个符号组成一个节点;4.重复步骤2. 3 ,直到概率和为1;5.从根节点开始到相应于每个符号的“树叶”,概率大的标“0”,概率小的标“1”;6.从根节点开始,对符号进行编码;7.译码时流程逆向进行,从文件中读出哈夫曼树,并利用哈夫曼树将编码序列解码。
哈夫曼编译码的设计与实现

哈夫曼编\译码的设计与实现一、简介1.设计目的:通过对简单哈夫曼编/译码系统的设计与实现来熟练掌握树型结构在实际问题中的应用。
2.问题的描述:利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。
但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接收端将传来的数据进行译码。
系统应该具有如下的几个功能:接收原始数据、编码、译码、打印编码规则。
二、数据结构的设计:1.哈夫曼结点结构体:typedef struct HtNode{int weight;int parent, lchild, rchild;}HtNode;2.哈夫曼树结构体:typedef struct HtTree{struct HtNode ht[MAXNODE+1];int root;}HtTree, *PHtTree;三、功能(函数)设计:总体上划分为四个模块,具体功能描述如下:1.初始化功能模块:接收输入信息,并正确输出2.建立哈夫曼树的功能模块:按照构造哈夫曼树的算法构造哈夫曼树,将HuffNode数组中的各个位置的各个域都添上相关的值3.哈夫曼编码的功能模块:根据输入的相关字符信息进行哈夫曼编码,然后将结果存入,同时将字符与0、1代码串的一一对应关系打印到屏幕上。
4.译码的功能模块:接收需要译码的0、1代码串,按照哈夫曼编码规则将其翻译成字符集中的字符所组成的字符串形式,将翻译的结果在屏幕上输出四、界面设计:该界面操做简单,内容详细,便于程序使用者根据提示轻松上手。
简洁明朗是该界面最大的特点。
哈夫曼编/译码请逐个输入结点和结点的权值>>>按Enter键开始根据此提示界面进入程序使用阶段。
请输入结点个数:根据用户输入结点个数,动态输入并存储字符及权值然后输出字符与0、1代码串的对应关系。
进入以下界面,进行后续操作1----------------------------编码2----------------------------译码3----------------------------重新输入权值;0----------------------------退出用户键入“0”,即可出编码译码操作五、程序设计:1.函数功能说明及其程序流程图的描述:1>:main函数:控制整个程序的整个流程。
哈夫曼编码译码器系统.

目录一、系统开发的背景 (1)二、系统分析与设计 (1)三、系统的设计与实现 (2)(一)设计初始化(Initialization) (2)(二)设计编码(Encoding) (3)(三)设计译码(Decoding) (3)(四)设计印代码文件(Print) (4)(五)设计印哈夫曼树(TreePrinting) (4)四、系统测试 (5)(一)测试main函数 (5)(二)测试编码(Encoding)及译码(Decoding)函数 (5)(三)测试印代码文件(Print)函数 (6)(四)测试相关的根目录 (6)五、总结 (6)六、附件(代码、部分图表) (7)哈夫曼编/译码器系统一、系统开发的背景为了提高信道利用率,缩短信息传输时间,降低传输成本,且在信息发送端通过一个编码系统对待传数据预先编码,在信息接收端将传来的数据进行译码(复原),因此设计哈夫曼编码/译码器系统。
二、系统分析与设计(一)系统功能要求:【任务要求】I:初始化(Initialization)。
从终端读入字符集大小n,以及n个字符和n个权值,建立哈夫曼树,并将它存于文件hfmTree中。
E:编码(Encoding)。
利用以建好的哈夫曼树(如不在内存,则从文件hfmTree 中读入),对文件To Be Tran中的正文进行编码,然后将结果存入文件CodeFile 中。
D:译码(Decoding)。
利用已建好的哈夫曼树将文件Code File中的代码进行译码,结果存入文件Text File中。
P:印代码文件(Print)。
将文件Code File以紧凑格式显示在终端上,每行50个代码。
同时将此字符形式的编码文件写入文件Code Prin中。
T:印哈夫曼树(Tree Printing)。
将已在内存中的哈夫曼树以直观的方式(树或凹入表形式)显示在终端上,同时将此字符形式的哈夫曼树写入文件Tree Print中。
【测试数据】利用教科书中的数据调试程序。
哈夫曼编码译码器实验报告

哈夫曼编码译码器实验报告实验名称:哈夫曼编码译码器实验一、实验目的: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)接收原始数据:从终端读入字符集大小n,以及n个字符和n个权值,建立哈夫曼树,并将它存于文件nodedata.dat中。
(2)编码:利用已建好的哈夫曼树(如不在内存,则从文件nodedata.dat 中读入),对文件中的正文进行编码,然后将结果存入文件code.dat中。
(3)译码:利用已建好的哈夫曼树将文件code.dat中的代码进行译码,结果存入文件text中。
(4)打印编码规则:即字符与编码的一一对应关系。
(5)打印哈夫曼树:将已在内存中的哈夫曼树以直观的方式显示在终端上。
二、数据结构设计1、构造哈夫曼树时,使用静态链表作为哈夫曼树的存储。
在构造哈夫曼树时,设计一个结构体数组HuffNode保存哈夫曼树中各结点的信息,根据二叉树的性质可知,具有n个叶子结点的哈夫曼树共有2n-1个结点,所以数组HuffNode的大小设置为2n-1,描述结点的数据类型为:typedef struct{int weight;int parent;int lchild;int rchild;char inf;}HNodeType;2.求哈夫曼编码时使用一维结构数组HuffCode作为哈夫曼编码信息的存储。
求哈夫曼编码实际上就是在已建立的哈夫曼树中,从叶子结点开始,沿结点的双亲链域回退到根结点,每回退一步,就走过了哈夫曼的一个分支,从而得到一位哈夫曼编码值。
由于一个字符的哈夫曼编码就是从根结点到相应叶子结点所经过的路径上各分支所组成的0、1序列,因此先得到的分支代码为所求编码的低位码,后得到的分支代码为所求的高位码。
数据结构实验,哈夫曼编码译码系统

数据结构实验,哈夫曼编码译码系统展开全文1. 实验名称: 二叉树的基本操作及哈夫曼编码译码系统的实现2.实验目的:创建一棵二叉树,实现先序、中序和后序遍历一棵二叉树,计算二叉树结点个数等操作。
哈夫曼编码/译码系统。
3. 实验任务:能成功演示二叉树的有关运算,运算完毕后能成功释放二叉树所有结点占用的系统内存。
4. 实验内容(1)在二叉链表上实现二叉树运算a) 设计递归算法,实现二叉树的基本运算:删除一棵二叉树,求一棵二叉树的高度,求一棵二叉树中叶子结点数,复制一棵二叉树,交换一棵二叉树的左右子树。
b) 设计算法,按自上到下,自左到右的次序,即按层次遍历一棵二叉树。
c) 设计main函数,测试上述每个运算。
d) 提示:队列结构可以辅助进行层次遍历,队列的元素类型是指向二叉树结点的指针类型。
(2)哈夫曼编码和译码系统a) 设计一个菜单可以循环显示B——建树:读入字符集和各字符频度,建立哈夫曼树。
T——遍历:先序和中序遍历二叉树。
E——生成编码:产生每个字符的哈夫曼编码。
C——编码:输入由字符集中字符组成的任意字符串,利用已经生成的哈夫曼编码进行编码,显示编码结果。
D——译码:利用已建成的哈夫曼树进行译码。
X——退出。
b) 提示:修改二叉树结点类BTNode,增加一个指向双亲的parent域,修改二叉树类的函数MakeTree设置该域的值;可以通过遍历哈夫曼树生成每个叶子结点的哈夫曼编码。
5. 概要设计1) 二叉树首先定义结点类BTNode包括对结点的访问,打印,交换结点左右元素等操作。
并将二叉树类BTree声明为友元类。
二叉树类中包含了建树,判断二叉树是否为空,求结点数,求高度,删除,交换左右子树,三种次序遍历及按层次遍历,清空二叉树等函数。
在主函数中调用实现这些功能。
类和类的层次设计主要算法:PreOrder:输出当前结点元素,左右孩子递归调用函数。
InOrder:左孩子递归调用函数,输出当前结点元素,右孩子递归调用。
哈夫曼编码和译码系统(附源代码)

实训报告题目:哈夫曼编码和译码系统院系:专业:姓名:学号:指导教师:日期:一.需求分析•二.概要设计(1)建立哈夫曼树、编码•(2)字符匹配•(3)哈夫曼树遍历• 3三.详细设计及编码实现•3四.流程图(1)总流程图75(2)编码实现流程图・16(3)译码实现流程图・17五.调试分析(1 )计算权值-18(1)生成哈夫曼树,建立编码表• 18 (3)将输入字符编码 19( 4 )输入新的字符串,进行译码 19( 5)输入新的二进制数将其译为字符 20六 . 系统维护 20 七.实验总结 20八. 源代码 21一.需求分析《1》问题描述:在传送电文时,人们总是希望传送时间尽可能短,这就是要求使电文代码长度尽可能短。
利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。
但是,这要求在发送端通过一个编码系统能够对待传输数据预先编码,在接收端将传来的数据进行译码。
对于双工信道(即可以双向传输信息的信道),每段都需要一个完整的编/译系统。
所以为这样的信息收发站写一个哈夫曼的编译码系统。
《2》打开一篇英文文章,统计该文章中每个字符出现的次数,然后以它们作为权值,对每一个字符进行编码,编码完成后再对其编码进行译码。
问题补充:1.从硬盘的一个文件里读出一段英语文章。
2.统计这篇文章中的每个字符出现的次数。
3.以字符出现字数作为权值,构建哈夫曼树,并将哈夫曼树的存储结构的初态和终态进行输出。
4.对每个字符进行编码并将所编码写入文件然后对所编码进行编译。
《3》这个哈夫曼编码译码主要是以英文字母输入进行编码与编译,编码译码过程由系统自动完成,人工操作部分就是电文的录入,和编译出来时的读操作。
.概要设计本程序主要用到了三个算法。
(1)哈夫曼树建立、编码在初始化(I)的过程中间,要用输入的字符和权值建立哈夫曼树并求得哈夫曼编码。
先将输入的字符和权值存放到一个结构体数组中,建立哈夫曼树,将计算所得的哈夫曼编码存储到另一个结构体数组中。
课程设计报告--哈夫曼编码译码系统

2.定义代表森林的数组,在创建哈夫曼树的过程当中保存被选中的字符,即给定报文中出现的字符,模拟哈夫曼树选取和删除左右子树的过程;
3.自底而上地创建哈夫曼树,保存根的地址和每个叶节点的地址,即字符的地址,然后自底而上检索,首尾对换调整为哈夫曼树实现哈弗曼编码;
随着计算机的普遍应用与日益发展,其应用早已不局限于简单的数值运算,而涉及到问题的分析、数据结构框架的设计以及设计最短路线等复杂的非数值处理和操作。算法与数据结构的学习就是为以后利用计算机资源高效地开发非数值处理的计算机程序打下坚实的理论、方法和技术基础。
算法与数据结构旨在分析研究计算机加工的数据对象的特性,以便选择适当的数据结构和存储结构,从而使建立在其上的解决问题的算法达到最优。
4.定义hufnode类型的全局数组hufNode[256],在编码时最为哈夫曼编码对照表的节点,char型c保存字符,int code[100]保存其哈夫曼编码;
5.定义HFM类,主要保存哈夫曼树的根节点指针,但其丰富的功能函数将实现哈夫曼编码译码的工作及其他功能;
函数介绍:
1.void init(signode * sig){……}初始化数组SN[];
数据结构是在整个计算机科学与技术领域上广泛被使用的术语。它用来反映一个数据的内部构成,即一个数据由那些成分数据构成,以什么方式构成,呈什么结构。数据结构有逻辑上的数据结构和物理上的数据结构之分。逻辑上的数据结构反映成分数据之间的逻辑关系,而物理上的数据结构反映成分数据在计算机内部的存储安排。数据结构是数据存在的形式。
《数据结构》主要介绍一些最常用的数据结构,阐明各种数据结构内在的逻辑关系,讨论其在计算机中的存储表示,以及在其上进行各种运算时的实现算法,并对算法的效率进行简单的分析和讨论。数据结构是介于数学、计算机软件和计算机硬件之间的一门计算机专业的核心课程,它是计算机程序设计、数据库、操作系统、编译原理及人工智能等的重要基础,广泛的应用于信息学、系统工程等各种领域。
哈夫曼编码译码器

default : printf("%c", p+96);
}
p1 = p; //让p1记住p
p = 59; //这里p要重置为59,因为经过上面的程序p已经变化了,不重置为1则HT[p].lchild!=0||HT[p].rchild!=0所以for语句无法进行!!!!
RedType r[MAXSIZE+1]; //r[0]闲置用作哨兵
int length; //顺序表长度
}SqList;
/**************************************************全局变量*************************************************************/
HuffmanTree HT; //赫夫曼树
HuffmanCode HC; //码值
FILE *fp, *fp1, *fp2;
int a[30] = {0};
float b[30];
void minweight()
{
float Weight = 0;
int i;
for (i = 0 ; i < 30 ; i++)
Weight = Weight + strlen(HC[i+1])*b[i];
printf("最小权值是:%f\n",Weight);
float *w; //权
/****************************************测试解码(可以输入一个不正确的二进制码串)**************************************/
数据结构课程设计哈夫曼编码译码器

题目一: 哈夫曼编码与译码一、任务设计一个运用哈夫曼算法的编码和译码系统, 反复地显示并解决以下项目, 直到选择退出为止。
规定: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.一个完整的系统应具有以下功能:1)初始化(Initialzation)。
从数据文件 DataFile.data 中读入字符及每个字符的权值,建立哈夫曼树HuffTree;2)编码(EnCoding)。
用已建好的哈夫曼树,对文件ToBeTran.data 中的文本进行编码形成报文,将报文写在文件 Code.txt 中;3)译码(Decoding)。
利用已建好的哈夫曼树,对文件CodeFile.data 中的代码进行解码形成原文,结果存入文件 Textfile.txt 中;4)输出(Output)。
输出 DataFile.data 中出现的字符以及各字符出现的频度(或概率);输出 ToBeTran.data 及其报文 Code.txt;输出 CodeFile.data 及其原文 Textfile.txt;要求:所设计的系统应能在程序执行的过程中,根据实际情况(不同的输入)建立DataFile.data、ToBeTran.data 和 CodeFile.data 三个文件,以保证系统的通用性。
二、实验目的:理解哈夫曼树的特征及其应用;在对哈夫曼树进行理解的基础上,构造哈夫曼树,并用构造的哈夫曼树进行编码和译码;通过该实验,使学生对二叉树的构建、遍历等以及哈夫曼编码的应用有更深层次的理解。
实验步骤:实验分 2 次完成第 1 次:完成程序的主框架设计,进行调试,验证其正确性;(2学时)第 2 次:详细设计,进行调试,对运行结果进行分析,完成实验报告。
哈夫曼编码译码系统

自己用c++写的哈夫曼编码/译码系统,经过反复测试,绝对没问题,请放心使用。
3、哈夫曼编码/译码系统(树应用)[问题描述]利用哈夫曼编码进行通信,可以压缩通信的数据量,提高传输效率,缩短信息的传输时间,还有一定的保密性。
现在要求编写一程序模拟传输过程,实现在发送前将要发送的字符信息进行编码,然后进行发送,接收后将传来的数据进行译码,即将信息还原成发送前的字符信息。
[实现提示]在本例中设置发送者和接受者两个功能,发送者的功能包括:①输入待传送的字符信息;②统计字符信息中出现的字符种类数和各字符出现的次数(频率);②根据字符的种类数和各自出现的次数建立哈夫曼树;③利用以上哈夫曼树求出各字符的哈夫曼编码;④将字符信息转换成对应的编码信息进行传送。
接受者的功能包括:①接收发送者传送来的编码信息;②利用上述哈夫曼树对编码信息进行翻译,即将编码信息还原成发送前的字符信息。
从以上分析可发现,在本例中的主要算法有三个:(1)哈夫曼树的建立;(2)哈夫曼编码的生成;(3)对编码信息的翻译。
测试结果源代码#include<iostream.h>#include<iomanip.h>#include<string.h>#include <windows.h>typedef struct {int weight;int parent,lchild,rchild;char data;}HTNode,*HuffmanTree;typedef char **HuffmanCode;void tongji(char *a,int *w,char *d,int &n) {int j=0;for(int i=0;i<100&&a[i]!='\0';i++){for(int k=0;k<j;k++){if(a[i]==d[k]){ w[k]++;break;}}if(k==j){d[j]=a[i];w[j]++;j++;}}n=j;d[j]='\0';}void HuffmanCoding(HuffmanTree &HT,HuffmanCode &HC,int *w,int n,char *d) { if(n<=1)return;int m=2*n-1;HT=new HTNode[m+1];HuffmanTree p;int i;for(p=HT+1,i=1;i<=n;i++,++p){ p->data=d[i-1];p->lchild=p->parent=p->rchild=0;p->weight=w[i-1]; }for(;i<=m;++i,++p) {p->lchild=p->parent=p->rchild=0;p->weight=0; }for(i=n+1;i<=m;++i){int s1,s2,u,t;for (u=1;u<=i-1;u++)if(HT[u].parent==0){s1=u;break;}for(u=u+1;u<=i-1;u++) {if(HT[s1].weight>HT[u].weight&&HT[u].parent==0)s1=u; }for(t=1;t<=i-1;t++)if(HT[t].parent==0&&t!=s1){s2=t;break;}for(t=t+1;t<=i-1;t++){ if(HT[s2].weight>HT[t].weight&&HT[t].parent==0&&t!=s1)s2=t; }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; }HC=new char*[n+1];char *cd=new char[n];cd[n-1]='\0';int start,c,f;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';HC[i]=new char[n-start];strcpy(HC[i],&cd[start]); }delete(cd);}void bianma(HuffmanCode HC,char *a,char *d,char *bc) {int m1=0,m2=0;int i=0,j;while(a[i]!='\0') {j=0;while(d[j]!='\0') {if (a[i]==d[j]){ m1=0;while(HC[j+1][m1]!='\0')bc[m2++]=HC[j+1][m1++];break; }j++; } i++; }bc[m2]='\0';}void yima(HuffmanTree HT,int n,char*bc){ int m=2*n-1; for (int i=0;bc[i]!='\0';++i){ if (HT[m].lchild==0) {cout<<HT[m].data;m=2*n-1; }if(bc[i]=='0')m=HT[m].lchild;elsem=HT[m].rchild; }cout<<HT[m].data<<endl;}void main(){char a[100];char d[100];char bc[1000];int w[100],n=0;HuffmanTree HT;HuffmanCode HC;cout<<"请输入字符:\n";cin>>a;for(int ak=0;ak<100;ak++)w[ak]=0;tongji(a,w,d,n);HuffmanCoding(HT,HC,w,n,d);cout<<"霍夫曼编码为:"<<endl;cout<<"原码"<<"权值"<<"二进制码"<<endl;for(int s=0;s<n;s++)cout<<d[s]<<" "<<w[s]<<" "<<HC[s+1]<<endl;bianma(HC,a,d,bc);cout<<"密文为:";cout<<bc<<endl;cout<<"开始译码:"<<endl;yima(HT,n,bc);}。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
题目:哈夫曼编码和译码系统院系:专业:姓名:学号:指导教师:日期:实训报告目录一、前言 (1)二、需求分析 (1)1.问题描述 (1)2.基本要求 (1)3.根据需求,该系统应具备以下功能......................2.三、概要设计 (2)1.哈夫曼编码和译码的方法概述 (2)2.流程图 (3)四、详细设计 (4)1.用类来定义变量和函数 (4)2.构造哈夫曼树 (5)3.根据哈夫曼树进行哈夫曼编码 (6)4.输出对应的哈夫曼编码表 (7)5.对输入的字符进行编码 (8)6.对输入的编码进行译码 (9)7.主函数 (10)五、调试分析 (13)六、实验总结 (16)一、前言在这个信息高速发展的时代,每时每刻都进行着大量的信息传递,到处都离不开信息,它贯穿在人们日常的生活之中,对人们产生的影响日趋扩大,而利用哈夫曼码进行通信则可以大大提高信道利用率,缩短通信传输时间,降低传输成本。
在生产中则可以更大可能的降低成本从而获得更大里润,这也是信息时代发展的趋势所在。
本次实训设计的是哈夫曼编码和译码系统,建立一个简易的系统,对于给定的一篇英文文章,统计字符出现的概率,并根据概率建立Huffman树,利用Huffman 编码对文章进行编码和译码。
掌握Huffman树的建立与应用,并进一步熟练掌握程序的设计流程。
这是个拥有完整功能的系统程序,对将所学到的知识运用到实践中,在设计的同时,培养了学生各方面的能力。
二、需求分析1.问题描述在传送电文时,人们总是希望传送时间尽可能短,这就是要求使电文代码长度尽可能短。
利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。
但是,这要求在发送端通过一个编码系统能够对待传输数据预先编码,在接收端将传来的数据进行译码,所以为这样的信息收发站写一个哈夫曼的编译码系统。
2.基本要求输入一段英文原文,构造哈夫曼树,生成对应的编码表,输出原文对应的编码,或者是根据已生成的编码表,输入一段二进制数编码,得到对应的字符原文。
3.根据需求,该系统应具备以下功能对给出的字符以及字符的权值构造哈夫曼树,生成对应的编码表输入一段原文,对原文进行编码输入二进制编码,输出对应的原文三、概要设计1.哈夫曼编码和译码的方法概述初始化,每个字符就是一个结点,对应节点的权值大小,选取权值最小的两个结点,以它们为儿子,构造出一个新的结点;新结点的权值就是它两个儿子的权值之和;构造之后,从原来的结点序列里删除刚才选出的那两个结点,但同时将新生成的结点加进去;如果结点序列里只剩下一个结点,表示构造完毕,退出。
否则回到第一步。
对某个结点而言,其左孩子在当前阶段的编码为0,右孩子的编码为1,这样就可以通过遍历树来生成字符一一对应的编码表来到这里,基本上艰苦的已经完成了,对某个具体的字符串编码和解码就只是简单的“查表——替换”的工作了。
译码:译码也是个简单的查表--替换过程。
如果利用该种编码发送字符串,则它的“字符——编码”对应表也必须发送过去,然后对给出的一串编码,从左向右,将编码组合起来并查表,一旦找到有匹配的字符,则将当前的编码替换为对应的字符。
因为该编码是不会出现”某一个字符的编码是另一个字符编码的缀”这种情况的,也就是不会出现类似于“A 为00而B 为0010”这样的情况,所以译码出来的字符串是唯一的,而且就是原来进行编码的那一个。
2.流程图四、详细设计1.用类来定义变量和函数class Node //节点类{public:friend Hafuman;char data; //结点值int weight; //权值int parent; //双亲结点int lchild; //左孩子结点int rchild; //右孩子结点void CreateHT(Node ht[], int n);void CreateHCode(Node ht[], Hafuman hcd[], int n);};class Hafuman{public:friend Node;char cd[N]; //存放哈夫曼码int start; //从start开始读cd中的哈夫曼码void DispHCode(Node ht[], Hafuman hcd[], int n);void editHCode(Node ht[], Hafuman hcd[], int n);void deHCode(Node ht[], Hafuman hcd[], int n);};2.构造哈夫曼树void Node::CreateHT( Node ht[], int n) {int i, k, lnode, rnode;int min1, min2;for (i = 0; i<2 * n - 1; i++)ht[i].parent = ht[i].lchild = ht[i].rchild = -1; //所有结点的相关域置初值-1for (i = n; i<2 * n - 1; i++) //构造哈夫曼树{min1 = min2 = 32767; //int的范围是-32768—32767lnode = 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; //两个最小节点的父节点是iht[i].weight = ht[lnode].weight + ht[rnode].weight; //两个最小节点的父节点权值为两个最小节点权值之和ht[i].lchild = lnode; ht[i].rchild = rnode; //父节点的左节点和右节点}}3.根据哈夫曼树进行哈夫曼编码void Node::CreateHCode(Node ht[], Hafuman hcd[], int n){int i, f, c;Hafuman hc;for (i = 0; i<n; i++) //根据哈夫曼树求哈夫曼编码{hc.start = n; c = i;f = ht[i].parent;while (f != -1) //循序直到树根结点结束循环{if (ht[f].lchild == c) //处理左孩子结点hc.cd[hc.start--] = '0';else //处理右孩子结点hc.cd[hc.start--] = '1';c = f; f = ht[f].parent;}hc.start++; //start指向哈夫曼编码hc.cd[]中最开始字符hcd[i] = hc;}}4.输出对应的哈夫曼编码表void Hafuman::DispHCode(Node ht[], Hafuman hcd[], int n){int i, k;cout << " 输出哈夫曼编码:\n";for (i = 0; i<n; i++) //输出data中的所有数据,即A-Z{ cout<<"\t"<<ht[i].data<<":";for (k = hcd[i].start;k<=n; k++)//输出所有data中数据的编码{ cout<< hcd[i].cd[k];}cout<<"\n";}}5.对输入的字符进行编码void Hafuman::editHCode(Node ht[], Hafuman hcd[], int n) {char string[MAXSIZE];int i, j, k;cin>> string; //把要进行编码的字符串存入string数组中cout<<"\n输出编码结果:\n";for (i = 0; string[i] != '#'; i++) //#为终止标志{for (j = 0; j<n; j++){if (string[i] == ht[j].data || string[i] == ht[j].data+32)//循环查找与输入字符相同的编号,相同的就输出这个字符的编码{for (k = hcd[j].start; k <= n; k++){cout<< hcd[j].cd[k];}break; //输出完成后跳出当前for循环}}}}6.对输入的编码进行译码void Hafuman::deHCode(Node ht[], Hafuman hcd[], int n) //译码函数{char code[MAXSIZE];int i, j, k, m, x,Knum = 50;cin>> code; //把要进行译码的字符串存入code数组中while (code[0] != '#')for (i = 0; i<n; i++){m = 0; //m为想同编码个数的计数器for (k = hcd[i].start,j=0;k<=n;k++,j++) //j为记录所存储这个字符的编码个数if (code[j] == hcd[i].cd[k]) //当有相同编码时m值加1m++;}if (m == j) //当输入的字符串与所存储的编码字符串个数相等时则输出这个的data数据{cout<< ht[i].data;for (x = 0; code[x - 1] != '#'; x++) //把已经使用过的code数组里的字符串删除{code[x] = code[x + j];}}Knum--;if (Knum < 1) { code[0] = '#';}}}7.主函数void main(){int n = 26, i;int x, flag = 1;Node a; Hafuman b;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[]= { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26 }; //初始化Node ht[M];Hafuman hcd[N];for (i = 0; i<n; i++) //把初始化的数据存入ht结构体中{ht[i].data = str[i];ht[i].weight = fnum[i];}while (flag) //菜单函数,当flag为0时跳出循环{cout<<"\n";cout<<"\n*************************************************";cout<<"\n ** 1--------------显示编码-----------1 **";cout<<"\n ** 2--------------进行编码-----------2 **";cout<<"\n ** 3--------------进行译码-----------3 **";cout<<"\n ** 4----------------退出-------------4 **";cout<<"\n*************************************************";cout<<"\n";cout<<"请输入选择的编号:";cin >>x;switch (x){case 1:system("cls"); //清屏函数a.CreateHT(ht, n);a.CreateHCode(ht, hcd, n);b.DispHCode(ht, hcd, n);cout<<"\n按任意键返回...";_getch();system("cls");break;case 2:system("cls");cout<<"请输入要进行编码的字符串(以#结束):\n";b.editHCode(ht, hcd, n);cout<<"\n按任意键返回...";_getch();system("cls");break;case 3:system("cls");b.DispHCode(ht, hcd, n);cout<<"请输入编码(以#结束):\n";b.deHCode(ht, hcd, n);cout<<"\n按任意键返回...";_getch();system("cls");break;case 4:flag = 0;break;default:system("cls");}}}五、调试分析一般情况下,为解决一个问题所编写的程序代码较长,可能包括几百条甚至成千上万条语句。