数据结构课程设计实验报告哈夫曼树的应用
数据结构课程设计实验报告哈夫曼树的应用.
计算机学院信管专业数据结构课程设计题目:哈夫曼树的应用班级:姓名:学号:同组人姓名:起迄日期:课程设计地点:指导教师:完成日期:2012年12月目录一、需求分析 (3)二、概要设计 (4)三、详细设计 (6)四、调试分析和测试结果 (7)五、心得体会和总结 (10)六、参考文献 (10)七、附录 (11)一、需求分析(一)实验要求要求用到数据结构课上学到的线性表的知识,所以就要充分而清晰的理解关于线性表的知识。
要求实现的基本功能很简单,只有删除和插入,增加功能也不过是加上修改。
这些在数据结构课上已经讲过,只要能够理解关于线性表的几个相关的基本算法就可以了。
问题是将输入的信息保存入文件和从文件输出。
这里基本是自学的内容,而且要考虑到是否要自行选择保存的磁盘。
综上,做这个课题,要具备的知识就是线性表的基本算法,文件的保存和读取算法,必要的C或者C++知识(本次我将使用C++实现),以及丰富的程序调适经验。
(二)实验任务一个完整的系统应具有以下功能:功能1.从终端读入字符集大小n,以及n个字符和n个权值,建立哈夫曼树并将它存于文件hfmTree中.将已在内存中的哈夫曼树以直观的方式(比如树)显示在终端上;功能2.利用已经建好的哈夫曼树(如不在内存,则从文件htmTree中读入),对文件ToBeTran中的正文进行编码,然后将结果存入文件CodeFile中,并输出结果,将文件CodeFile以紧凑格式先是在终端上,每行50个代码。
同时将此字符形式的编码文件写入文件CodePrint中。
功能3.利用已建好的哈夫曼树将文件CodeFile中的代码进行译码,结果存入文件TextFile中,并输出结果。
(三)实验步骤分步实施:1)初步完成总体设计,搭好框架,确定人机对话的界面,确定函数个数;2)完成最低要求:完成功能1;3)进一步要求:完成功能2和3。
有兴趣的同学可以自己扩充系统功能。
要求:1)界面友好,函数功能要划分好2)总体设计应画一流程图3)程序要加必要的注释4) 要提供程序测试方案5)程序一定要经得起测试,宁可功能少一些,也要能运行起来,不能运行的程序是没有价值的。
数据结构哈夫曼树的构造及其应用课程设计实验报告
目录第一章哈夫曼树的基本术语 (1)1.1路径和路径长度 (1)1.2树的带权路径长度 (1)1.3哈夫曼树的定义 (1)第二章哈夫曼树的构造 (2)2.1哈夫曼树的构造 (2)第三章哈夫曼树的存储结构及哈夫曼算法的实现 (3)3.1哈夫曼树的存储结构 (3)3.2 哈夫曼算法的简要描述 (3)第四章哈夫曼树的应用 (5)4.1哈夫曼编码 (5)4.2求哈夫曼编码的算法 (5)4.21思想方法 (5)4.22字符集编码的存储结构及其算法描述 (6)4.3哈夫曼树和编码程序实现: (6)4.4程序运行结果: (9)心得体会 (10)参考文献 (10)第一章哈夫曼树的基本术语1.1路径和路径长度在一棵树中,从一个结点往下可以达到的孩子或子孙结点之间的通路,称为路径。
通路中分支的数目称为路径长度。
若规定根结点的层数为1,则从根结点到第L层结点的路径长度为L-1。
1.2结点的权及带权路径长度若将树中结点赋给一个有着某种含义的数值,则这个数值称为该结点的权。
结点的带权路径长度为:从根结点到该结点之间的路径长度与该结点的权的乘积。
1.2树的带权路径长度树的带权路径长度(Weighted Path Length of Tree):也称为树的代价,定义为树中所有叶结点的带权路径长度之和,通常记为:其中:n表示叶子结点的数目wi和li分别表示叶结点ki的权值和根到结点ki之间的路径长度。
1.3哈夫曼树的定义在权为wl ,w2,…,wn的n个叶子所构成的所有二叉树中,带权路径长度最小(即代价最小)的二叉树称为最优二叉树或哈夫曼树。
[例]给定4个叶子结点a,b,c和d,分别带权7,5,2和4。
构造如下图所示的三棵二叉树(还有许多棵),它们的带权路径长度分别为:(a)WPL=7*2+5*2+2*2+4*2=36(b)WPL=7*3+5*3+2*1+4*2=4(c)WPL=7*1+5*2+2*3+4*3=35其中(c)树的WPL最小,可以验证,它就是哈夫曼树。
数据结构课程设计哈夫曼树的应用
哈夫曼树的应用课程设计3合1 《数据结构与算法》课程设计指导教师:班级:学号:姓名:《数据结构与算法》课程设计目录一、前言1.摘要2.《数据结构与算法》课程设计任务书二、实验目的三、题目--赫夫曼编码/译码器1.问题描述2.基本要求3.测试要求4.实现提示四、需求分析--具体要求五、概要设计六、程序说明七、详细设计八、实验心得与体会前言1.摘要随着计算机的普遍应用与日益发展,其应用早已不局限于简单的数值运算,而涉及到问题的分析、数据结构框架的设计以及设计最短路线等复杂的非数值处理和操作。
算法与数据结构的学习就是为以后利用计算机资源高效地开发非数值处理的计算机程序打下坚实的理论、方法和技术基础。
算法与数据结构旨在分析研究计算机加工的数据对象的特性,以便选择适当的数据结构和存储结构,从而使建立在其上的解决问题的算法达到最优。
数据结构是在整个计算机科学与技术领域上广泛被使用的术语。
它用来反映一个数据的内部构成,即一个数据由那些成分数据构成,以什么方式构成,呈什么结构。
数据结构有逻辑上的数据结构和物理上的数据结构之分。
逻辑上的数据结构反映成分数据之间的逻辑关系,而物理上的数据结构反映成分数据在计算机内部的存储安排。
数据结构是数据存在的形式。
《数据结构》主要介绍一些最常用的数据结构,阐明各种数据结构内在的逻辑关系,讨论其在计算机中的存储表示,以及在其上进行各种运算时的实现算法,并对算法的效率进行简单的分析和讨论。
数据结构是介于数学、计算机软件和计算机硬件之间的一门计算机专业的核心课程,它是计算机程序设计、数据库、操作系统、编译原理及人工智能等的重要基础,广泛的应用于信息学、系统工程等各种领域。
学习数据结构是为了将实际问题中所涉及的对象在计算机中表示出来并对它们进行处理。
通过课程设计可以提高学生的思维能力,促进学生的综合应用能力和专业素质的提高。
2.《数据结构与算法》课程设计任务书《数据结构与算法》是计算机专业重要的核心课程之一,在计算机专业的学习过程中占有非常重要的地位。
哈夫曼树的应用数据结构课程设计
《数据结构》课程设计报告题目:哈夫曼树应用学生姓名:谢辉学号: 201317010201专业班级:计科13102同组姓名:赵丽娜指导教师:徐晓蓉设计时间:2014年下学期第18周目录一、需求分析 (2)1. 分析问题 (2)2. 确定解决方案 (2)3. 输入的形式和输入值的范围 (3)4.输出的形式 (3)5.程序所能达到的功能 (3)二、概要设计 (4)1. 主程序的流程图: (4)2.程序中数据类型的定义: (4)3.各程序模块之间的层次(调用)关系: (4)三、详细设计 (5)1.哈夫曼树存储及类的定义: (5)2.哈夫曼树的基本操作: (6)3.主函数 (7)1. 测试数据及其输出结果: (9)2. 调试过程中遇到的问题及解决办法: (13)五、总结 (14)七、致谢 (14)八、附录 (14)一、需求分析1.分析问题利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。
但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接收端将传来的数据进行译码(复原)。
对于双工信道(即可以双向传输信息的信道),每端都需要一个完整的编/译码系统。
为这样的信息收发站写一个哈夫曼码的编/译码系统。
2.确定解决方案设计建立带权的哈夫曼树,确定哈夫曼树的类与成员函数,以及各函数之间的调用关系,采用动态数组的存储结构存储所需要的数据,通过不同的函数来实现编码,译码以及打印二进制编码、哈夫曼树,把不同的数据存入不同的txt文件中,通过主函数调用来实现功能检测。
3.输入的形式和输入值的范围手动或者从文本中读入数据的形式初始化哈夫曼树,从键盘中或者文件中读入数据,以字母A-Z代表结点,以自然数代表权值,字符串提示使用者所要执行的操作。
4.输出的形式在显示器界面上或者以文本的形式来实现程序调试的输出。
5.程序所能达到的功能(1)I:初始化(Initialization)。
从终端读入字符集大小n,以及n个字符和n 个权值,建立哈夫曼树,并将它存于文件hfmTree中。
哈夫曼树_实验报告
一、实验目的1. 理解哈夫曼树的概念及其在数据结构中的应用。
2. 掌握哈夫曼树的构建方法。
3. 学习哈夫曼编码的原理及其在数据压缩中的应用。
4. 提高编程能力,实现哈夫曼树和哈夫曼编码的相关功能。
二、实验原理哈夫曼树(Huffman Tree)是一种带权路径长度最短的二叉树,又称为最优二叉树。
其构建方法如下:1. 将所有待编码的字符按照其出现的频率排序,频率低的排在前面。
2. 选择两个频率最低的字符,构造一棵新的二叉树,这两个字符分别作为左右子节点。
3. 计算新二叉树的频率,将新二叉树插入到排序后的字符列表中。
4. 重复步骤2和3,直到只剩下一个节点,这个节点即为哈夫曼树的根节点。
哈夫曼编码是一种基于哈夫曼树的编码方法,其原理如下:1. 从哈夫曼树的根节点开始,向左子树走表示0,向右子树走表示1。
2. 每个叶子节点对应一个字符,记录从根节点到叶子节点的路径,即为该字符的哈夫曼编码。
三、实验内容1. 实现哈夫曼树的构建。
2. 实现哈夫曼编码和译码功能。
3. 测试实验结果。
四、实验步骤1. 创建一个字符数组,包含待编码的字符。
2. 创建一个数组,用于存储每个字符的频率。
3. 对字符和频率进行排序。
4. 构建哈夫曼树,根据排序后的字符和频率,按照哈夫曼树的构建方法,将字符和频率插入到哈夫曼树中。
5. 实现哈夫曼编码功能,遍历哈夫曼树,记录从根节点到叶子节点的路径,即为每个字符的哈夫曼编码。
6. 实现哈夫曼译码功能,根据哈夫曼编码,从根节点开始,按照0和1的路径,找到对应的叶子节点,即为解码后的字符。
7. 测试实验结果,验证哈夫曼编码和译码的正确性。
五、实验结果与分析1. 构建哈夫曼树根据实验数据,构建的哈夫曼树如下:```A/ \B C/ \ / \D E F G```其中,A、B、C、D、E、F、G分别代表待编码的字符。
2. 哈夫曼编码根据哈夫曼树,得到以下字符的哈夫曼编码:- A: 00- B: 01- C: 10- D: 11- E: 100- F: 101- G: 1103. 哈夫曼译码根据哈夫曼编码,对以下编码进行译码:- 00101110111译码结果为:BACGACG4. 实验结果分析通过实验,验证了哈夫曼树和哈夫曼编码的正确性。
赫夫曼树实验报告
赫夫曼树实验报告赫夫曼树实验报告引言:赫夫曼树是一种用于数据压缩的重要算法,它通过构建一棵二叉树来实现对数据的编码和解码。
本次实验旨在通过实际操作,深入了解赫夫曼树的原理和应用,并验证其在数据压缩中的有效性。
一、实验背景数据压缩在现代信息技术中起着至关重要的作用。
随着数据量的不断增加,如何有效地压缩数据成为了一个迫切的问题。
赫夫曼树作为一种经典的数据压缩算法,具有较高的压缩比和较快的解压速度,因此备受关注。
二、实验目的1. 了解赫夫曼树的原理和构建方法;2. 掌握赫夫曼编码的过程和步骤;3. 验证赫夫曼树在数据压缩中的有效性。
三、实验过程1. 构建赫夫曼树首先,我们需要统计待压缩数据中各个字符的出现频率。
然后,按照频率从小到大的顺序,将字符构建成一棵二叉树。
具体构建方法为:每次选取频率最低的两个字符,将它们作为左右子节点,生成一个新的节点,该节点的频率为左右子节点频率之和。
重复此过程,直到所有字符都被构建成树的节点。
2. 进行赫夫曼编码在赫夫曼树构建完成后,我们需要对每个字符进行编码。
编码的规则是:向左走为0,向右走为1。
从根节点开始,对每个字符进行路径搜索,直到找到对应的叶子节点,记录下路径上的0和1,即为该字符的编码。
3. 数据压缩与解压缩利用赫夫曼编码,我们可以对待压缩数据进行压缩。
将每个字符替换为对应的编码后,将所有编码拼接起来,即可得到压缩后的数据。
解压缩则是将编码根据赫夫曼树进行反向解码,得到原始数据。
四、实验结果通过实验,我们将不同类型的数据进行了压缩和解压缩,并与原始数据进行了对比。
结果表明,赫夫曼树在数据压缩中表现出色,能够显著减小数据的大小,同时保持数据的完整性。
五、实验总结赫夫曼树作为一种高效的数据压缩算法,具有广泛的应用前景。
通过本次实验,我们深入了解了赫夫曼树的原理和构建方法,并验证了其在数据压缩中的有效性。
赫夫曼树的应用不仅可以提高数据传输的效率,还可以节省存储空间,对于大数据时代的到来具有重要意义。
数据结构哈夫曼树实验报告
数据结构哈夫曼树实验报告一、实验内容本次实验的主要内容是哈夫曼树的创建和编码解码。
二、实验目的1. 理解并掌握哈夫曼树的创建过程;2. 理解并掌握哈夫曼编码的原理及其实现方法;3. 掌握哈夫曼树的基本操作,如求哈夫曼编码和哈夫曼解码等;4. 学习如何组织程序结构,运用C++语言实现哈夫曼编码和解码。
三、实验原理哈夫曼树的创建:哈夫曼树的创建过程就是一个不断合并权值最小的两个叶节点的过程。
具体步骤如下:1. 将所有节点加入一个无序的优先队列里;2. 不断地选出两个权值最小的节点,并将它们合并成为一个节点,其权值为这两个节点的权值之和;3. 将新的节点插入到队列中,并继续执行步骤2,直到队列中只剩下一棵树,这就是哈夫曼树。
哈夫曼编码:哈夫曼编码是一种无损压缩编码方式,它根据字符出现的频率来构建编码表,并通过编码表将字符转换成二进制位的字符串。
具体实现方法如下:1. 统计每个字符在文本中出现的频率,用一个数组记录下来;2. 根据字符出现的频率创建哈夫曼树;3. 从根节点开始遍历哈夫曼树,给左分支打上0的标记,给右分支打上1的标记。
遍历每个叶节点,将对应的字符及其对应的编码存储在一个映射表中;4. 遍历文本中的每个字符,查找其对应的编码表,并将编码字符串拼接起来,形成一个完整的编码字符串。
哈夫曼解码就是将编码字符串还原为原始文本的过程。
具体实现方法如下:1. 从根节点开始遍历哈夫曼树,按照编码字符串的位数依次访问左右分支。
如果遇到叶节点,就将对应的字符记录下来,并重新回到根节点继续遍历;2. 重复步骤1,直到编码字符串中的所有位数都被遍历完毕。
四、实验步骤1. 定义编码和解码的结构体以及相关变量;3. 遍历哈夫曼树,得到每个字符的哈夫曼编码,并将编码保存到映射表中;4. 将文本中的每个字符用其对应的哈夫曼编码替换掉,并将编码字符串写入到文件中;5. 使用哈夫曼编码重新构造文本,并将结果输出到文件中。
五、实验总结通过本次实验,我掌握了哈夫曼树的创建和哈夫曼编码的实现方法,也学会了如何用C++语言来组织程序结构,实现哈夫曼编码和解码。
哈夫曼树 实验报告
哈夫曼树实验报告哈夫曼树实验报告引言:哈夫曼树是一种经典的数据结构,广泛应用于数据压缩、编码和解码等领域。
本次实验旨在通过构建哈夫曼树,探索其原理和应用。
一、哈夫曼树的定义和构建方法哈夫曼树是一种特殊的二叉树,其叶子节点对应于待编码的字符,而非叶子节点则是字符的编码。
构建哈夫曼树的方法是通过贪心算法,即每次选择权值最小的两个节点合并,直到构建出完整的哈夫曼树。
二、哈夫曼编码的原理和实现哈夫曼编码是一种可变长度编码,即不同字符的编码长度不同。
其原理是通过构建哈夫曼树来确定字符的编码,使得频率较高的字符编码较短,频率较低的字符编码较长。
这样可以有效地减少编码的长度,从而实现数据的压缩。
三、实验过程和结果在本次实验中,我们选择了一段文本作为输入数据,通过统计每个字符的频率,构建了对应的哈夫曼树。
然后,根据哈夫曼树生成了字符的编码表,并将原始数据进行了编码。
最后,我们通过对编码后的数据进行解码,验证了哈夫曼编码的正确性。
实验结果显示,通过哈夫曼编码后,原始数据的长度明显减少,达到了较好的压缩效果。
同时,解码后的数据与原始数据完全一致,证明了哈夫曼编码的可靠性和正确性。
四、哈夫曼树的应用哈夫曼树在实际应用中有着广泛的用途。
其中,最典型的应用之一是数据压缩。
通过使用哈夫曼编码,可以将大量的数据压缩为较小的存储空间,从而节省了存储资源。
此外,哈夫曼树还被广泛应用于网络传输、图像处理等领域,提高了数据传输的效率和图像的质量。
五、对哈夫曼树的思考哈夫曼树作为一种经典的数据结构,其优势在于有效地减少了数据的冗余和存储空间的占用。
然而,随着技术的不断发展,现代的数据压缩算法已经不再局限于哈夫曼编码,而是采用了更为复杂和高效的算法。
因此,我们需要在实际应用中综合考虑各种因素,选择合适的压缩算法。
六、总结通过本次实验,我们深入了解了哈夫曼树的原理和应用。
哈夫曼编码作为一种重要的数据压缩算法,具有广泛的应用前景。
在实际应用中,我们需要根据具体情况选择合适的压缩算法,以达到最佳的压缩效果和性能。
哈夫曼树实验报告
哈夫曼树实验报告一、实验目的1.理解哈夫曼树的概念和实现原理;2.掌握使用哈夫曼树进行编码和解码的方法;3.熟悉哈夫曼树在数据压缩中的应用。
二、实验原理哈夫曼树是一种用于数据压缩的树形结构,通过将出现频率较高的数据项用较短的编码表示,从而达到压缩数据的目的。
哈夫曼树的构建过程如下:1.统计字符出现的频率,并按照频率从小到大排序;2.将频率最低的两个字符合并为一个节点,节点的频率为两个字符的频率之和;3.将新节点插入频率表,并将频率表重新排序;4.重复步骤2和3,直到频率表中只剩下一个节点,该节点即为哈夫曼树的根节点。
三、实验步骤1.统计输入的字符序列中每个字符出现的频率;2.根据频率构建哈夫曼树;3.根据哈夫曼树生成字符的编码表;4.将输入的字符序列编码为哈夫曼编码;5.根据哈夫曼树和编码表,解码得到原始字符序列。
四、实验结果以字符序列"abacabad"为例进行实验:1.统计字符频率的结果为:a-4次,b-2次,c-1次,d-1次;```a-4/\b-2c-1/\d-1空节点```3.根据哈夫曼树生成的编码表为:a-0,b-10,c-110,d-111;5. 根据哈夫曼树和编码表进行解码得到原始字符序列:"abacabad"。
五、实验总结通过本次实验,我深入了解了哈夫曼树的原理和实现方法,掌握了使用哈夫曼树进行字符编码和解码的过程。
哈夫曼树在数据压缩中的应用非常广泛,能够有效地减小数据的存储空间,提高数据传输效率。
在实际应用中,我们可以根据不同字符出现的频率构建不同的哈夫曼树,从而实现更高效的数据压缩和解压缩算法。
数据结构课程设计报告-哈夫曼树
计算机科学学院数据结构课程设计题目:基于哈夫曼树的文件压缩/解压程序学生姓名:***学号:************专业:计算机科学与技术班级:12级(2)班指导教师姓名及职称:陈明讲师起止时间:2014 年3 月——2014 年4 月1 需求分析1.1课题背景及意义近年来,随着计算机技术的发展,多媒体计算机技术、计算机网络技术以及现代多媒体通信技术正在向着信息化、高速化、智能化迅速发展。
各个领域的应用与发展,各个系统的数据量越来越大,给数据的存储、传输以及有效、快速获取信息带来了严重的障碍。
数据压缩技术能够比较有效地解决这个问题。
还有在最近几年中兴起的物联网和云计算都是对海量的数据进行处理和传输的,如果不对数据进行压缩,那么数据传输所需的带宽要求就很高,物理成本上也随之上升。
所以说数据压缩在计算机通信中占有很重要的位置,且涉及领域多,应用广泛,与我们的生活息息相关。
1.2课题要求1.2.1.实现一个基于哈夫曼树的文件压缩程序和文件解压程序。
1.2.2.压缩程序能输入源文件进行压缩,输出压缩文件;1.2.3.解压程序读入压缩文件,根据相应的哈夫曼编码解压还原,得到对应的源文件。
1.2.4.可选做:求出压缩率;打印哈夫曼树;对文件夹压缩;图形图形化窗口操作界面。
1.3任务和要求1.3.1选择1时:输入一个待压缩的文本文件名称(可带路径)。
如:D:\1\XXX.txt压缩文件名称= D:\1\XXX.zip1.3.2选择2时:输入一个待解压的压缩文件名称(可带路径)。
如:D:\1\YYY.txt解压文件名称=D:\1\YYY.zip2概要设计2.1问题解决的思路概述图1 主程序流程图2.2 算法思想:2.2.1输入要压缩的文件首先运行的时候,用户主界面上有菜单提示该如何使用软件,根据菜单提示选择所要执行的项,依次进行,因为各个环节之间有先后顺序。
第一步为输入压缩软件的名称,由键盘输入文件路径和文件名称,读入字符数组中,打开该文件,按照提示进行压缩。
数据结构课程设计实验报告哈夫曼
数据结构课程设计实验报告哈夫曼树的应用计算机学院信管专业数据结构课程设计题目:哈夫曼树的应用班级:姓名:学号:同组人姓名:起迄日期:课程设计地点:指导教师:完成日期:2012年12月目录一、需求分析 (3)二、概要设计 (4)三、详细设计 (6)四、调试分析和测试结果 (7)五、心得体会和总结 (10)六、参考文献 (10)七、附录 (11)一、需求分析(一)实验要求要求用到数据结构课上学到的线性表的知识,所以就要充分而清晰的理解关于线性表的知识。
要求实现的基本功能很简单,只有删除和插入,增加功能也不过是加上修改。
这些在数据结构课上已经讲过,只要能够理解关于线性表的几个相关的基本算法就可以了。
问题是将输入的信息保存入文件和从文件输出。
这里基本是自学的内容,而且要考虑到是否要自行选择保存的磁盘。
综上,做这个课题,要具备的知识就是线性表的基本算法,文件的保存和读取算法,必要的C或者C++知识(本次我将使用C++实现),以及丰富的程序调适经验。
(二)实验任务一个完整的系统应具有以下功能:功能1.从终端读入字符集大小n,以及n个字符和n个权值,建立哈夫曼树并将它存于文件hfmTree中.将已在内存中的哈夫曼树以直观的方式(比如树)显示在终端上;功能2.利用已经建好的哈夫曼树(如不在内存,则从文件htmTree中读入),对文件ToBeTran中的正文进行编码,然后将结果存入文件CodeFile中,并输出结果,将文件CodeFile以紧凑格式先是在终端上,每行50个代码。
同时将此字符形式的编码文件写入文件CodePrint中。
功能3.利用已建好的哈夫曼树将文件CodeFile中的代码进行译码,结果存入文件TextFile中,并输出结果。
(三)实验步骤分步实施:1)初步完成总体设计,搭好框架,确定人机对话的界面,确定函数个数;2)完成最低要求:完成功能1;3)进一步要求:完成功能2和3。
有兴趣的同学可以自己扩充系统功能。
哈弗曼树实验报告(3篇)
一、实验目的1. 理解并掌握哈弗曼树的构建原理。
2. 学会使用哈弗曼树进行数据编码和解码。
3. 了解哈弗曼编码在数据压缩中的应用。
二、实验原理哈弗曼树(Huffman Tree)是一种带权路径长度最短的二叉树,用于数据压缩。
其基本原理是:将待编码的字符集合按照出现频率从高到低排序,构造一棵二叉树,使得叶子节点代表字符,内部节点代表编码,权值代表字符出现的频率。
通过这棵树,可以生成每个字符的编码,使得编码的平均长度最小。
三、实验环境1. 操作系统:Windows 102. 编程语言:C++3. 开发工具:Visual Studio 2019四、实验步骤1. 构建哈弗曼树(1)创建一个结构体`HuffmanNode`,包含字符、权值、左子树和右子树指针。
```cppstruct HuffmanNode {char data;int weight;HuffmanNode left;HuffmanNode right;};(2)定义一个函数`HuffmanTree()`,用于创建哈弗曼树。
```cppHuffmanNode HuffmanTree(std::vector<char>& chars, std::vector<int>& weights) {// 创建初始二叉树std::vector<HuffmanNode> trees;for (int i = 0; i < chars.size(); ++i) {trees.push_back(new HuffmanNode{chars[i], weights[i], nullptr, nullptr});}// 构建哈弗曼树while (trees.size() > 1) {// 选择两个权值最小的节点auto it1 = std::min_element(trees.begin(), trees.end(),[](HuffmanNode a, HuffmanNode b) {return a->weight < b->weight;});auto it2 = std::next(it1);HuffmanNode parent = new HuffmanNode{0, it1->weight + it2->weight, it1, it2};// 删除两个子节点trees.erase(it1);trees.erase(it2);// 将父节点添加到二叉树集合中trees.push_back(parent);}// 返回哈弗曼树根节点return trees[0];}```2. 生成哈弗曼编码(1)定义一个函数`GenerateCodes()`,用于生成哈弗曼编码。
数据结构实验报告(哈夫曼树)
数据结构实验报告实验题目:Huffman编码与解码姓名:学号:院系:实验名称:Huffman编码与解码实验问题描述:本实验需要以菜单形式完成以下功能:1.输入电文串2.统计电文串中各个字符及其出现的次数3.构造哈弗曼树4.进行哈弗曼编码5.将电文翻译成比特流并打印出来6.将比特流还原成电文数据结构的描述:逻辑结构:本实验可用二叉树实现,其逻辑结构为一对二的形式,即一个结点对应两个结点。
在实验过程中我们也应用到了栈的概念。
存储结构:使用结构体来对数据进行存储:typedef struct{int weight;int parent,lc,rc;}HTNode,*HuffmanTree;typedef struct LNode{char *elem;int stacksize;int top;}SqStack;在main函数里面定义一个哈弗曼树并实现上述各种功能。
程序结构的描述:本次实验一共构造了10个函数:1.void HuffTree(HuffmanTree &HT,int n[],int mun);此函数根据给定的mun个权值构建哈弗曼树,n[]用于存放num个权值。
2.void Select(HuffmanTree &HT,int n,int i,int &s1,int &s2);此函数用于在HT[1,i-1]中选择parent为0且weight为最小的两个结点,其下标分别为s1,s2.3.void HuffmanCoding(HuffmanTree HT,char **&HC,int n);此函数从哈弗曼树HT上求得n 个叶子结点的哈弗曼编码并存入数组HC中。
4.void Coding(HuffmanTree HT,char **HC,int root,SqStack &S);此函数用于哈弗曼编码,先序遍历哈弗曼树HT,求得每个叶子结点的编码字符串,存入数组HC,S为一个顺序栈,用来记录遍历路径,root是哈弗曼数组HT中根结点的位置下标。
数据结构实验哈夫曼树及哈夫曼编码c语言
数据结构实验报告:哈夫曼树及哈夫曼编码一、实验目的1. 理解哈夫曼树及哈夫曼编码的概念和原理;2. 掌握C语言中哈夫曼树及哈夫曼编码的实现方法;3. 分析和讨论哈夫曼编码在实际应用中的优势和不足。
二、实验内容和步骤1. 哈夫曼树的构建1.1 通过C语言实现哈夫曼树的构建算法;1.2 输入一组权值,按哈夫曼树构建规则生成哈夫曼树;1.3 输出生成的哈夫曼树结构,并进行可视化展示。
2. 哈夫曼编码的实现2.1 设计哈夫曼编码的实现算法;2.2 对指定字符集进行编码,生成哈夫曼编码表;2.3 对给定字符串进行哈夫曼编码,并输出编码结果。
三、实验过程及结果1. 哈夫曼树的构建在C语言中,通过定义结构体和递归算法实现了哈夫曼树的构建。
根据输入的权值,依次选择权值最小的两个节点构建新的父节点,直至构建完成整棵哈夫曼树。
通过调试和可视化展示,确认了程序正确实现了哈夫曼树的构建。
2. 哈夫曼编码的实现经过分析和设计,利用哈夫曼树的特点实现了哈夫曼编码的算法。
根据生成的哈夫曼树,递归地生成字符对应的哈夫曼编码,并输出编码结果。
对指定的字符串进行了编码测试,验证了哈夫曼编码的正确性和有效性。
四、实验结果分析1. 哈夫曼编码在数据传输和存储中具有较高的压缩效率和可靠性,能够有效减少数据传输量和存储空间;2. 哈夫曼树及哈夫曼编码在通信领域、数据压缩和加密等方面有着广泛的应用和重要意义;3. 在实际应用中,哈夫曼编码的构建和解码算法需要较大的时间和空间复杂度,对于大规模数据的处理存在一定的局限性。
五、实验总结通过本次实验,深入理解了哈夫曼树及哈夫曼编码的理论知识,并掌握了C语言中实现哈夫曼树及哈夫曼编码的方法。
对哈夫曼编码在实际应用中的优势和局限性有了更深入的认识,这对今后的学习和工作有着积极的意义。
六、参考文献1. 《数据结构(C语言版)》,严蔚敏赵现军著,清华大学出版社,2012年;2. 《算法导论》,Thomas H. Cormen 等著,机械工业出版社,2006年。
数据结构哈夫曼树实验报告
数据结构哈夫曼树实验报告一、实验目的本次实验的主要目的是深入理解和掌握哈夫曼树的数据结构及其相关算法,并通过实际编程实现来提高对数据结构的应用能力和编程技能。
二、实验环境本次实验使用的编程环境为具体编程语言名称,操作系统为具体操作系统名称。
三、实验原理哈夫曼树,又称最优二叉树,是一种带权路径长度最短的二叉树。
其基本原理是通过构建一棵二叉树,使得权值较大的节点距离根节点较近,权值较小的节点距离根节点较远,从而达到带权路径长度最小的目的。
在构建哈夫曼树的过程中,首先需要将所有的节点按照权值从小到大进行排序。
然后,选取权值最小的两个节点作为左右子树,构建一个新的父节点,该父节点的权值为左右子节点权值之和。
重复这个过程,直到所有的节点都被构建到哈夫曼树中。
哈夫曼编码是基于哈夫曼树的一种编码方式。
对于每个叶子节点,从根节点到该叶子节点的路径上,向左的分支编码为 0,向右的分支编码为 1,这样就可以得到每个叶子节点的哈夫曼编码。
四、实验步骤1、定义节点结构体```ctypedef struct HuffmanNode {char data;int weight;struct HuffmanNode left;struct HuffmanNode right;} HuffmanNode;```2、实现节点排序函数```cvoid sortNodes(HuffmanNode nodes, int n) {for (int i = 0; i < n 1; i++){for (int j = 0; j < n i 1; j++){if (nodesj>weight > nodesj + 1>weight) {HuffmanNode temp = nodesj;nodesj = nodesj + 1;nodesj + 1 = temp;}}}}```3、构建哈夫曼树```cHuffmanNode buildHuffmanTree(HuffmanNode nodes, int n) {while (n > 1) {sortNodes(nodes, n);HuffmanNode left = nodes0;HuffmanNode right = nodes1;HuffmanNode parent =(HuffmanNode )malloc(sizeof(HuffmanNode));parent>data ='\0';parent>weight = left>weight + right>weight;parent>left = left;parent>right = right;nodes0 = parent;nodes1 = nodesn 1;n;}return nodes0;}```4、生成哈夫曼编码```cvoid generateHuffmanCodes(HuffmanNode root, int codes, int index) {if (root>left) {codesindex = 0;generateHuffmanCodes(root>left, codes, index + 1);}if (root>right) {codesindex = 1;generateHuffmanCodes(root>right, codes, index + 1);}if (!root>left &&!root>right) {printf("%c: ", root>data);for (int i = 0; i < index; i++){printf("%d", codesi);}printf("\n");}}```5、主函数```cint main(){HuffmanNode nodes5 ={(HuffmanNode )malloc(sizeof(HuffmanNode)),(HuffmanNode )malloc(sizeof(HuffmanNode)),(HuffmanNode )malloc(sizeof(HuffmanNode)),(HuffmanNode )malloc(sizeof(HuffmanNode)),(HuffmanNode )malloc(sizeof(HuffmanNode))};nodes0>data ='A';nodes0>weight = 5;nodes1>data ='B';nodes1>weight = 9;nodes2>data ='C';nodes2>weight = 12;nodes3>data ='D';nodes3>weight = 13;nodes4>data ='E';nodes4>weight = 16;HuffmanNode root = buildHuffmanTree(nodes, 5);int codes100;generateHuffmanCodes(root, codes, 0);return 0;}```五、实验结果与分析通过运行上述程序,得到了每个字符的哈夫曼编码:A: 00B: 01C: 10D: 110E: 111分析实验结果可以发现,权值较小的字符A 和B 对应的编码较短,而权值较大的字符D 和E 对应的编码较长。
数据结构实验三哈夫曼树实验报告
题目:哈夫曼编/译码器一、题目要求:写一个哈夫曼码的编/译码系统,要求能对要传输的报文进行编码和解码。
构造哈夫曼树时,权值小的放左子树,权值大的放右子树,编码时右子树编码为1,左子树编码为0.二、概要设计:数据结构:typedef struct{int bit[MAXBIT];int start;} HCodeType; /* 编码结构体 */typedef struct{int weight;int parent;int lchild;int rchild;char value;} HNode; /* 结点结构体 */函数:void DEMONHuffmanTree (HNode HuffNode[MAXNODE], int n)作用:构造一个哈夫曼树,并循环构建int main ()作用:运用已经构建好的哈弗曼树,进行节点的处理,达到成功解码编译三、详细设计:哈夫曼树的建立:void DEMONHuffmanTree (HNode HuffNode[MAXNODE], int n){int i = 0, j, m1, m2, x1, x2;char x;/* 初始化存放哈夫曼树数组 HuffNode[] 中的结点 */while (i<n){HuffNode[i].weight = 0;arent =-1;HuffNode[i].lchild =-1;HuffNode[i].rchild =-1;scanf("%c",&x);scanf("%c",&HuffNode[i].value); eight);}for (i=n; i<2*n-1; i++){HuffNode[i].weight = 0;arent =-1;HuffNode[i].lchild =-1;HuffNode[i].rchild =-1;HuffNode[i].value=i;}/* 循环构造 Huffman 树 */for (i=0; i<n-1; i++){m1=m2=MAXQZ; eight < m1 && HuffNode[j].parent==-1){m2=m1;eight;x1=j;}else if (HuffNode[j].weight < m2 && HuffNode[j].parent==-1) {m2=HuffNode[j].weight;x2=j;}} /* end for *//* 设置找到的两个子结点 x1、x2 的父结点信息 */HuffNode[x1].parent = n+i;HuffNode[x2].parent = n+i;HuffNode[n+i].weight = HuffNode[x1].weight + HuffNode[x2].weight; HuffNode[n+i].lchild = x1;HuffNode[n+i].rchild = x2;}}叶子节点的哈夫曼编码的保存:for (j=+1; j<n; j++)HuffCode[i].bit[j] = [j];HuffCode[i].start = ;主函数展示:int main(){HNode HuffNode[MAXNODE];HCodeType HuffCode[MAXLEAF],cd;int i, j, c, p, n,k=0;char wen[100];char z;scanf ("%d", &n);HuffmanTree (HuffNode, n);for (i=0; i < n; i++){= n-1;c = i;p = HuffNode[c].parent;while (p != -1) /* 父结点存在 */{if (HuffNode[p].lchild == c)[] = 0;else[] = 1;; /* 求编码的低一位 */c=p;p=HuffNode[c].parent; /* 设置下一循环条件 */ } /* end while */for (j=+1; j<n; j++)HuffCode[i].bit[j] = [j];HuffCode[i].start = ;} /* end for */z=getchar();z=getchar();for(;z!='\n';z=getchar()){wen[k++]=z;for(i=0;i<n;i++){if(z==HuffNode[i].value){for (j=HuffCode[i].start+1; j < n; j++)printf ("%d", HuffCode[i].bit[j]);break;}else;}}printf("\n");for(i=0;i<k;i++){printf("%c",wen[i]);}printf("\n");return 0;}四、调试分析与心得体会:虽然哈夫曼树的建立有书上的参考,但是实际写整个代码的时候还是问题重重。
数据结构实验赫夫曼树的建立和应用
数据结构实验赫夫曼树的建立和应用概述赫夫曼树(Huffman Tree),又称最优二叉树(Optimal Binary Tree),是一种特殊的二叉树,常用于数据压缩算法中。
赫夫曼树的主要特点是,树中距离根节点较近的叶子节点的权值较小,距离根节点较远的叶子节点的权值较大。
本文将介绍赫夫曼树的建立过程和一些应用场景。
赫夫曼树的建立赫夫曼树的建立过程主要包含以下几个步骤:1.统计待编码的字符出现的频率,得到频率表。
2.将频率表中的字符和频率作为叶子节点,构成一个森林。
3.每次从森林中选择两个权值最小的节点(可以是叶子节点也可以是非叶子节点),合并为一个新的节点,并将该节点重新插入森林中。
4.重复上述步骤,直到森林中只剩下一个根节点,即为赫夫曼树的根节点。
下面是一个示例:字符频率A6B3C4D2E5根据以上频率表,我们可以构建下面的赫夫曼树: 20/ \\10 10/ \\ / \\5 5 4 6/ \\2 3赫夫曼编码赫夫曼编码是一种前缀编码的方式,即没有任何编码是其他编码的前缀。
赫夫曼编码通过将赫夫曼树中经过的路径用0或1进行编码,实现对字符的压缩。
在上面的例子中,赫夫曼编码如下:字符编码A10B110C111D00E01可以看到,编码表中每个字符的编码都是其他字符的前缀,符合赫夫曼编码的要求。
赫夫曼树的应用赫夫曼树在数据压缩领域有广泛的应用,常用于压缩文本文件。
通过统计字符出现的频率,并建立赫夫曼树和编码表,可以将原始文本中的字符用更短的二进制位来表示,从而达到压缩数据的目的。
除了数据压缩,赫夫曼树还可以应用于其他领域,例如网络数据传输中的数据压缩、图像编码等。
总结赫夫曼树是一种特殊的二叉树,通过统计字符出现的频率,建立赫夫曼树,并生成对应的赫夫曼编码表,可以实现对数据的压缩。
赫夫曼树在数据压缩领域有广泛的应用,可以大幅度减小数据存储和传输的开销。
需要注意的是,在使用赫夫曼树进行数据压缩时,对于频率较低的字符可能会出现编码较长的情况,这可能会导致压缩效果不佳。
哈夫曼树实验报告
一、实验目的1. 理解哈夫曼树的基本概念和构造方法。
2. 掌握哈夫曼编码的原理和实现过程。
3. 通过实验加深对数据结构中树型结构应用的理解。
二、实验原理哈夫曼树(Huffman Tree)是一种带权重的二叉树,用于实现哈夫曼编码。
其基本思想是:将字符按照在数据集中出现的频率进行排序,然后选取两个最小频率的字符合并成一个新节点,其频率为两个字符频率之和,重复此过程,直到只剩下一个节点,即为哈夫曼树的根节点。
哈夫曼编码是一种基于哈夫曼树的编码方法,其原理是将每个字符映射到一个唯一的二进制序列,序列的长度与字符在数据集中出现的频率成反比。
频率越高,编码的长度越短,从而提高信息传输的效率。
三、实验环境1. 操作系统:Windows 102. 编程语言:C++3. 开发环境:Visual Studio 2019四、实验步骤1. 初始化(1)从数据文件中读取字符及其频率。
(2)构建一个优先队列(最小堆),将字符和频率存储在队列中。
2. 构建哈夫曼树(1)从优先队列中取出两个频率最小的节点,合并成一个新节点,其频率为两个节点频率之和。
(2)将新节点插入优先队列中。
(3)重复步骤(1)和(2),直到优先队列中只剩下一个节点,即为哈夫曼树的根节点。
3. 哈夫曼编码(1)遍历哈夫曼树,从根节点到叶子节点的路径上,左子树表示0,右子树表示1。
(2)将每个叶子节点的字符和对应的编码存储在哈夫曼编码表中。
4. 编码(1)读取待编码的文本。
(2)根据哈夫曼编码表,将文本中的每个字符映射到对应的编码。
(3)将编码序列写入文件。
5. 译码(1)读取编码文件。
(2)从哈夫曼树的根节点开始,根据编码序列的每一位,判断是左子树还是右子树。
(3)当到达叶子节点时,输出对应的字符。
(4)重复步骤(2)和(3),直到编码序列结束。
五、实验结果与分析1. 实验结果(1)成功构建了哈夫曼树,并生成了哈夫曼编码表。
(2)对给定的文本进行了编码和译码,验证了编码的正确性。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
计算机学院信管专业数据结构课程设计题目:哈夫曼树的应用班级:姓名:学号:同组人姓名:起迄日期:课程设计地点:指导教师:完成日期:2012年12月目录一、需求分析 (3)二、概要设计 (4)三、详细设计 (6)四、调试分析和测试结果 (7)五、心得体会和总结 (10)六、参考文献 (10)七、附录 (11)一、需求分析(一)实验要求要求用到数据结构课上学到的线性表的知识,所以就要充分而清晰的理解关于线性表的知识。
要求实现的基本功能很简单,只有删除和插入,增加功能也不过是加上修改。
这些在数据结构课上已经讲过,只要能够理解关于线性表的几个相关的基本算法就可以了。
问题是将输入的信息保存入文件和从文件输出。
这里基本是自学的内容,而且要考虑到是否要自行选择保存的磁盘。
综上,做这个课题,要具备的知识就是线性表的基本算法,文件的保存和读取算法,必要的C或者C++知识(本次我将使用C++实现),以及丰富的程序调适经验。
(二)实验任务一个完整的系统应具有以下功能:功能1.从终端读入字符集大小n,以及n个字符和n个权值,建立哈夫曼树并将它存于文件hfmTree中.将已在内存中的哈夫曼树以直观的方式(比如树)显示在终端上;功能2.利用已经建好的哈夫曼树(如不在内存,则从文件htmTree中读入),对文件ToBeTran中的正文进行编码,然后将结果存入文件CodeFile中,并输出结果,将文件CodeFile以紧凑格式先是在终端上,每行50个代码。
同时将此字符形式的编码文件写入文件CodePrint中。
功能3.利用已建好的哈夫曼树将文件CodeFile中的代码进行译码,结果存入文件TextFile中,并输出结果。
(三)实验步骤分步实施:1)初步完成总体设计,搭好框架,确定人机对话的界面,确定函数个数;2)完成最低要求:完成功能1;3)进一步要求:完成功能2和3。
有兴趣的同学可以自己扩充系统功能。
要求:1)界面友好,函数功能要划分好2)总体设计应画一流程图3)程序要加必要的注释4) 要提供程序测试方案5)程序一定要经得起测试,宁可功能少一些,也要能运行起来,不能运行的程序是没有价值的。
二、概要设计(一) 设计思想哈夫曼树用邻接矩阵作为存储结构,借助静态链表来实现遍历。
(二 ) 函数间的关系如图所示:(三)数据结构与算法设计哈夫曼编\译码器的主要功能是先建立哈夫曼树,然后利用建好的哈夫曼树生成哈夫曼编码后进行译码 。
在数据通信中,经常需要将传送的文字转换成由二进制字符0、1组成的二进制串,称之为编码。
构造一棵哈夫曼树,规定哈夫曼树中的左分之代表0,右分支代表1,则从根节点到每个叶子节点所经过的路径分支组成的0和1的序列便为该节点对应字符的编码,称之为哈夫曼编码。
最简单的二进制编码方式是等长编码。
若采用不等长编码,让出现频率高的字符具有较短的编码,让出现频率低的字符具有较长的编码,这样可能缩短传送电文的总长度。
哈夫曼树课用于构造使电文的编码总长最短的编码方案。
其主要流程图如下图所示。
哈夫曼树编\译码器流程图三、详细设计功能函数模块划分void main()void printhead()void printree(HuffmanTree HT,int w) //打印赫夫曼树void coprint(HuffmanTree start,HuffmanTree HT)//打印代码文件void printcode() //打印代码void decode() //完成译码功能void encode() //完成编码功能void inputcode()void init()void HuffmanCoding(HuffmanTree &HT,HuffmanCode &HC,int *w,int n)void select(HuffmanTree t,int i,int &s1,int &s2)int min(HuffmanTree t,int i)//找两个最小的权值(1)哈夫曼编码:首先定义函数,找出全部权值中最小的两个,然后定义一个变量,使他始终成为最小的那个。
再将两个函数最为叶子结点,并得到一个父亲节点,此父亲节点的权值为其叶子节点的权值之和。
并将此父亲节点的权值与其余权值进行比较,重新选出两个最小的权值,再进行上述步骤,直到所有权值形成了一颗二叉树,而此二叉树就是我们所说的最优二叉树,即哈夫曼树。
以上为哈夫曼树的建立过程,下面为哈夫曼编码的过程,从叶子节点出发,若此叶子节点为其父亲节点的左孩子,则将其编码为0,若为右孩子,则将其编码为1,然后为其父亲节点编码,若为祖先的左孩子,则变为0,为右孩子则为1,依次向上一层进行遍历,直到遍历到根节点,停止编码。
(2)译码:对于已经建好的哈夫曼树,要对其进行译码,首先从根出发如果编码为0,则往左孩子遍历,如果编码为1,则往右孩子遍历,直到遍历到叶子节点,便求得该子串相应的字符。
(3)初始化哈夫曼链表:首先输入结点个数,再将字符及权值输入,调用编码函数,得到每个字符编码并将其输出。
最后将哈夫曼编码写入文件。
(4)完成编码功能:打开目录下文件tobetran.txt,读取里面的字符,对其进行编码后,将编码写入目录下的codefile.txt中。
(5)完成译码功能:打开根目录下codefile.txt文件,读取里面的编码,对其中的编码进行译码,并将得到的内容写入根目录下的文件txtfile.txt中。
(6)打印编码(7)打印哈夫曼树四、调试分析和测试结果(一)初始化哈夫曼链表(二)编码字符(三)编码(四)译码(五)打印编码(六)打印哈夫曼函数五、心得体会与总结对于本次课程设计,主要是需要掌握哈夫曼树建立、哈夫曼编码以及哈夫曼译码的算法。
并能将其熟练应用于编译码器的完成。
经过这次的课程设计,使我们更加了解了数据结构,也更深入地了解了哈夫曼编码与译码算法,课程设计的题目比我们平常的实验内容要难,完成它不仅需要有厚实的语言基础,而且还要熟练掌握哈夫曼编码与译码的算法,另外对于文件的基本操作也需要熟悉。
通过数据结构课程设计,我的C++语言水平有了比较大的提高其中。
C++语言关于类的操作理解的比以前深刻不少。
另外是数据结构方面的提高对哈夫曼树的构造及哈夫曼码方面也有不少的提高。
在项目中也出现了很多的问题,最大的问题就是对程序设计框架结构的不了解,在实现代码与功能的连接时经常会出现各种不同的错误,在实现一些功能时系统常常会报错。
许多错误不知从哪修改以致拖了整个设计的后腿。
课程设计中,既回顾了很多以前的东西,也发现了很多的问题以前都没遇见过的,收获很大。
通过本次数据结构的课程设计,我学习了很多在上课没懂的知识,并对求哈夫曼树及哈夫曼编码/译码的算法有了更加深刻的了解,更巩固了课堂中学习有关于哈夫曼编码的知识。
此次哈夫曼树的应用系统的设计让自己对数据结构的了解更深入。
六、参考文献《C++面向对象程序设计教程》(第三版)陈维兴林小茶编著清华大学出版社《数据结构》(C语言版)严蔚民吴伟民编著清华大学出版社六、附录源程序:#include <iostream.h>#include <iomanip.h>#include <string.h>#include <malloc.h>#include <stdio.h>const int UINT_MAX=1000;typedef struct //哈夫曼树的存储表示{int weight; //权值int parent,lchild,rchild; //父节点,左孩子结点,右孩子结点}HTNode,* HuffmanTree; //动态分配数组存储哈夫曼树typedef char **HuffmanCode;//动态分配数组存储哈夫曼编码表//-----------全局变量-----------------------HuffmanTree HT; //代表哈夫曼树HuffmanCode HC; //代表哈夫曼编码int *w,i,j,n;char *z;int flag=0;int numb=0;// -----------------求哈夫曼编码-----------------------void line()//画分割线的函数{cout<<"\n--------------------------------------------------\n";}int min(HuffmanTree t,int i)//找两个最小的权值{int j,flag;int k=UINT_MAX; // 取k为不小于可能的值for(j=1;j<=i;j++)if(t[j].weight<k&&t[j].parent==0)k=t[j].weight,flag=j;t[flag].parent=1;return flag; //返回标识符}//--------------------使s1成为最小权值----------------------void select(HuffmanTree t,int i,int &s1,int &s2){int j;s1=min(t,i);s2=min(t,i);if(s1>s2)// s1为最小的两个值中序号较小的那个{j=s1;s1=s2;s2=j;}}void HuffmanCoding(HuffmanTree &HT,HuffmanCode &HC,int *w,int n){int m,i,s1,s2,start;int c,f;HuffmanTree p;char *cd;if(n<=1)return;m=2*n-1;//申请2n-1个内存单元HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode)); // 0号单元未用for(p=HT+1,i=1;i<=n;++i,++p,++w){p->weight=*w;//赋权值p->parent=0;p->lchild=0;p->rchild=0;}for(;i<=m;++i,++p)//初始化p->parent=0;for(i=n+1;i<=m;++i) // 建哈夫曼树{select(HT,i-1,s1,s2);//调用建子树的函数HT[s1].parent=HT[s2].parent=i;//i是s1和s2的父节点HT[i].lchild=s1;HT[i].rchild=s2;//s1和s2是i的儿子节点HT[i].weight=HT[s1].weight+HT[s2].weight;//i的权值为s1和s2的和}HC=(HuffmanCode)malloc((n+1)*sizeof(char*));//分配n个字符编码的头指针向量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';elsecd[--start]='1';HC[i]=(char*)malloc((n-start)*sizeof(char));//为第i个字符编码分配空间strcpy(HC[i],&cd[start]); //从cd复制编码(串)到HC }free(cd);//释放工作空间}//--------------初始化哈夫曼链表---------------------------------void init(){flag=1;int num;int num2;cout<<"下面初始化哈夫曼链表"<<endl<<"请输入结点的个数n:";cin>>num;//输入结点个数n=num;w=(int*)malloc(n*sizeof(int));//权值z=(char*)malloc(n*sizeof(char));//字符cout<<"\n请依次输入"<<n<<"个字符(字符型)\n注意:必须以回车结束:"<<endl;char temp[2];for(i=0;i<n;i++)//输入字符{cout<<"第"<<i+1<<"个字符:"<<endl;gets(temp);*(z+i)=*temp;}line();for(i=0;i<=n-1;i++)//输出字符{cout<<setw(6)<<*(z+i);}line();cout<<"\n请依次输入"<<n<<"个权值(\n注意:必须以回车结束):"<<endl;for(i=0;i<=n-1;i++)//输入权值{cout<<endl<<"第"<<i+1<<"个字符的权值:";cin>>num2;*(w+i)=num2;}HuffmanCoding(HT,HC,w,n);//调用哈夫曼编码//------------------------打印编码----------------------cout<<"字符对应的编码为:"<<endl;for(i=1;i<=n;i++)//输出所有编码{puts(HC[i]);}//--------------------------将哈夫曼编码写入文件---------cout<<"下面将赫夫曼编码写入文件"<<endl;FILE *htmTree;char r[]={' ','\0'};if((htmTree=fopen("htmTree.txt","w"))==NULL){cout<<"文件打开失败"<<endl;return;}fputs(z,htmTree);for(i=0;i<n+1;i++){fprintf(htmTree,"%6d",*(w+i));fputs(r,htmTree);}for(i=1;i<=n;i++){fputs(HC[i],htmTree);fputs(r,htmTree);}fclose(htmTree);cout<<"已将字符与对应编码写入根目录下文件htmTree.txt中"<<endl<<endl; }//init//---------------------获取字符并写入文件---------------------------------void inputcode(){FILE *virttran,*tobetran;char str[100];if((tobetran=fopen("tobetran.txt","w"))==NULL){cout<<"不能打开文件"<<endl;return;}cout<<"请输入你想要编码的字符"<<endl;gets(str);fputs(str,tobetran);cout<<"获取字符成功"<<endl;fclose(tobetran);}//------------------------------------------------------void encode() //完成编码功能{cout<<"下面对目录下文件tobetran.txt中的字符进行编码"<<endl;FILE *tobetran,*codefile;if((tobetran=fopen("tobetran.txt","rb"))==NULL){cout<<"不能打开文件"<<endl;}if((codefile=fopen("codefile.txt","wb"))==NULL){cout<<"不能打开文件"<<endl;}char *tran;i=99;tran=(char*)malloc(100*sizeof(char)); //为tran分配100个字节while(i==99){if(fgets(tran,100,tobetran)==NULL){cout<<"不能打开文件"<<endl;break;}for(i=0;*(tran+i)!='\0';i++){for(j=0;j<=n;j++){if(*(z+j-1)==*(tran+i)){fputs(HC[j],codefile);puts(HC[j]);if(j>n){cout<<"字符错误,无法编码!"<<endl;break;}}}}}cout<<"编码工作完成"<<endl<<"编码写入目录下的codefile.txt中"<<endl<<endl;fclose(tobetran);fclose(codefile);free(tran);}//--------------------------------------------------void decode() //完成译码功能{cout<<"下面对根目录下文件codefile.txt中的字符进行译码"<<endl;FILE *codef,*txtfile;if((txtfile=fopen("Textfile.txt","w"))==NULL){cout<<"不能打开文件"<<endl;}if ((codef=fopen("codefile.txt","r"))==NULL){cout<<"不能打开文件"<<endl;}char *tbdc,*outext,i2;int io=0,i,m;unsigned long length=10000;tbdc=(char*)malloc(length*sizeof(char)); //分配空间fgets(tbdc,length,codef);outext=(char*)malloc(length*sizeof(char)); //分配空间m=2*n-1;for(i=0;*(tbdc+i)!='\0';i++) //进入循环{i2=*(tbdc+i);if(HT[m].lchild==0){*(outext+io)=*(z+m-1);io++;m=2*n-1;i--;}else if(i2=='0') m=HT[m].lchild;else if(i2=='1') m=HT[m].rchild;}*(outext+io)='\0';fputs(outext,txtfile);cout<<"译码完成"<<endl<<"内容写入根目录下的文件txtfile.txt中"<<endl<<endl;free(tbdc);free(outext);fclose(txtfile);fclose(codef);}//---------------------------------------------void printcode() //打印代码{cout<<"下面打印根目录下文件CodePrin.txt中编码字符"<<endl<<"-----------------------------------------------------------------\n";FILE * CodePrin,* codefile;if((CodePrin=fopen("CodePrin.txt","w"))==NULL){cout<<"不能打开文件"<<endl;return;}if((codefile=fopen("codefile.txt","r"))==NULL){cout<<"不能打开文件"<<endl;return;}char *work3;work3=(char*)malloc(51*sizeof(char));do{if(fgets(work3,51,codefile)==NULL){cout<<"不能读取文件"<<endl;break;}fputs(work3,CodePrin);puts(work3);}while(strlen(work3)==50);free(work3);cout<<"打印工作结束"<<endl<<endl;fclose(CodePrin);fclose(codefile);}void coprint(HuffmanTree start,HuffmanTree HT)//打印代码文件{char t=' ';if(start!=HT){FILE * TreePrint;if((TreePrint=fopen("TreePrint.txt","a"))==NULL){cout<<"创建文件失败"<<endl;return;}numb++;//该变量为已被声明为全局变量coprint(HT+start->rchild,HT);if(start->lchild!=NULL&&start->rchild!=NULL) t='<';cout<<setw(5*numb)<<start->weight<<t<<endl;fprintf(TreePrint,"%d\n",start->weight);coprint(HT+start->lchild,HT);numb--;fclose(TreePrint);}}void printree(HuffmanTree HT,int w) //打印赫夫曼树{HuffmanTree p;p=HT+w;cout<<"下面打印赫夫曼树"<<endl; // 输出"打印赫夫曼树"语句coprint(p,HT);cout<<"打印工作结束"<<endl; //输出"打印工作结束"}void printhead(){cout<<"\t数据结构\t课程设计\t信管11101班伍瑶201117020126\n";cout<<"\n\t\t";cout<<"i.初始化赫夫曼链表w.编码字符\n\t\t";cout<<" e.编码 d.译码\n\t\t";cout<<"p.打印编码t.打印赫夫曼树\n\t\t";cout<<"q.退出\n\t\t";if(flag==0)cout<<"\n请先初始化赫夫曼链表,输入'i'\n";cout<<"请选择你要进行的操作:";}/*2.主程序*/void main(){char choice;while(choice!='q'){ printhead();cin>>choice;switch(choice){case 'i': //按下i则进行初始化赫夫曼链表,调用init函数init();break;case 'w': //按下w编码字符,调用inputcode函数inputcode();break;case 'e': //按下e编码,调用encode函数encode();break;case 'd': //按下d译码,调用decode函数decode();break;case 'p': //按下p打印编码,调用printcode函数printcode();break;case 't': //按下t打印赫夫曼树,调用printree函数printree(HT,2*n-1);break;case 'q': //按下q退出break;default:cout<<"输入错误,请重新选择"<<endl;}}free(z); //释放z结点free(w); //释放w结点free(HT); //释放HT结点}。