数据结构实验报告 哈夫曼树的实现
数据结构哈夫曼树实验报告

数据结构哈夫曼树实验报告一、实验目的本次实验的主要目的是深入理解和掌握哈夫曼树的数据结构及其相关算法,通过实际编程实现哈夫曼编码和解码的过程,提高对数据结构的应用能力和编程技能。
二、实验环境本次实验使用的编程语言为 Python,开发工具为 PyCharm。
操作系统为 Windows 10。
三、实验原理哈夫曼树(Huffman Tree),又称最优二叉树,是一种带权路径长度最短的二叉树。
其基本思想是通过构建一棵二叉树,使得权值较大的节点离根节点较近,权值较小的节点离根节点较远,从而实现带权路径长度的最小化。
哈夫曼编码是一种基于哈夫曼树的变长编码方式。
对于给定的字符集及其出现的频率,通过构建哈夫曼树,可以为每个字符生成唯一的编码,使得编码后的字符串总长度最短。
在构建哈夫曼树的过程中,首先将每个字符及其出现的频率作为一个独立的节点,然后按照频率从小到大的顺序进行合并,每次合并两个频率最小的节点,生成一个新的节点,其频率为两个子节点频率之和。
重复这个过程,直到所有节点合并为一个根节点,最终得到的二叉树即为哈夫曼树。
四、实验步骤1、定义节点类```pythonclass Node:def __init__(self, char, freq, left=None, right=None):selfchar = charselffreq = freqselfleft = leftselfright = rightdef __lt__(self, other):return selffreq < otherfreq```这个节点类包含了字符、频率以及左右子节点的信息,并实现了小于比较方法,以便在构建哈夫曼树时进行节点的排序。
2、构建哈夫曼树```pythondef build_huffman_tree(freq_dict):nodes = Node(char, freq) for char, freq in freq_dictitems()while len(nodes) > 1:nodessort()left = nodespop(0)right = nodespop(0)merged_freq = leftfreq + rightfreqnew_node = Node(None, merged_freq, left, right)nodesappend(new_node)return nodes0```该函数根据字符频率字典创建节点列表,然后不断合并频率最小的两个节点,直到只剩下一个节点,即哈夫曼树的根节点。
数据结构(C语言版)实验报告(哈夫曼树)

《数据结构与算法》实验报告一、需求分析1.问题描述:利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。
但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接收端将传来的数据进行译码(复原)。
对于双工通道(及可以双向传输信息的通道),每端都需要一个完整的编/译码系统。
试为这样的信息收发站写一个哈夫曼的编/译码系统。
2.基本要求一个完整的系统应具有以下功能:(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中。
3.测试数据(1)利用教科书例6-2中的数据调试程序。
(2)用下表给出的字符集和频度的实际统计数据建立哈夫曼树,并实现以下报文的编码和译码:“THIS PROGRAM IS MY FAVORITE”。
4,实现提示(1)编码结果以文本方式存储在文件CodeFile中。
(2)用户界面可以设计为“菜单”方式:显示上述功能符号,再加上“Q”表示退出运行Quit。
请用户键入一个选择功能符。
此功能执行完毕后再显示此菜单,直至某次用户选择了“Q”为止。
(3)在程序的一次执行过程中,第一次执行I、D或C命令之后,哈夫曼树已经在内存了,不必再读入。
哈夫曼树_实验报告

一、实验目的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. 实验目的本实验旨在通过实践理解哈夫曼编码的原理和实现方法,加深对数据结构中树的理解,并掌握使用Python编写哈夫曼编码的能力。
2. 实验原理哈夫曼编码是一种用于无损数据压缩的算法,通过根据字符出现的频率构建一棵哈夫曼树,并根据哈夫曼树对应的编码。
根据哈夫曼树的特性,频率较低的字符具有较长的编码,而频率较高的字符具有较短的编码,从而实现了对数据的有效压缩。
实现哈夫曼编码的主要步骤如下:1. 统计输入文本中每个字符的频率。
2. 根据字符频率构建哈夫曼树,其中树的叶子节点代表字符,内部节点代表字符频率的累加。
3. 遍历哈夫曼树,根据左右子树的关系对应的哈夫曼编码。
4. 使用的哈夫曼编码对输入文本进行编码。
5. 将编码后的二进制数据保存到文件,同时保存用于解码的哈夫曼树结构。
6. 对编码后的文件进行解码,还原原始文本。
3. 实验过程3.1 统计字符频率首先,我们需要统计输入文本中每个字符出现的频率。
可以使用Python中的字典数据结构来记录字符频率。
遍历输入文本的每个字符,将字符添加到字典中,并递增相应字符频率的计数。
```pythondef count_frequency(text):frequency = {}for char in text:if char in frequency:frequency[char] += 1else:frequency[char] = 1return frequency```3.2 构建哈夫曼树根据字符频率构建哈夫曼树是哈夫曼编码的核心步骤。
我们可以使用最小堆(优先队列)来高效地构建哈夫曼树。
首先,将每个字符频率作为节点存储到最小堆中。
然后,从最小堆中取出频率最小的两个节点,将它们作为子树构建成一个新的节点,新节点的频率等于两个子节点频率的和。
将新节点重新插入最小堆,并重复该过程,直到最小堆中只剩下一个节点,即哈夫曼树的根节点。
赫夫曼树实验报告

赫夫曼树实验报告赫夫曼树实验报告引言:赫夫曼树是一种用于数据压缩的重要算法,它通过构建一棵二叉树来实现对数据的编码和解码。
本次实验旨在通过实际操作,深入了解赫夫曼树的原理和应用,并验证其在数据压缩中的有效性。
一、实验背景数据压缩在现代信息技术中起着至关重要的作用。
随着数据量的不断增加,如何有效地压缩数据成为了一个迫切的问题。
赫夫曼树作为一种经典的数据压缩算法,具有较高的压缩比和较快的解压速度,因此备受关注。
二、实验目的1. 了解赫夫曼树的原理和构建方法;2. 掌握赫夫曼编码的过程和步骤;3. 验证赫夫曼树在数据压缩中的有效性。
三、实验过程1. 构建赫夫曼树首先,我们需要统计待压缩数据中各个字符的出现频率。
然后,按照频率从小到大的顺序,将字符构建成一棵二叉树。
具体构建方法为:每次选取频率最低的两个字符,将它们作为左右子节点,生成一个新的节点,该节点的频率为左右子节点频率之和。
重复此过程,直到所有字符都被构建成树的节点。
2. 进行赫夫曼编码在赫夫曼树构建完成后,我们需要对每个字符进行编码。
编码的规则是:向左走为0,向右走为1。
从根节点开始,对每个字符进行路径搜索,直到找到对应的叶子节点,记录下路径上的0和1,即为该字符的编码。
3. 数据压缩与解压缩利用赫夫曼编码,我们可以对待压缩数据进行压缩。
将每个字符替换为对应的编码后,将所有编码拼接起来,即可得到压缩后的数据。
解压缩则是将编码根据赫夫曼树进行反向解码,得到原始数据。
四、实验结果通过实验,我们将不同类型的数据进行了压缩和解压缩,并与原始数据进行了对比。
结果表明,赫夫曼树在数据压缩中表现出色,能够显著减小数据的大小,同时保持数据的完整性。
五、实验总结赫夫曼树作为一种高效的数据压缩算法,具有广泛的应用前景。
通过本次实验,我们深入了解了赫夫曼树的原理和构建方法,并验证了其在数据压缩中的有效性。
赫夫曼树的应用不仅可以提高数据传输的效率,还可以节省存储空间,对于大数据时代的到来具有重要意义。
赫夫曼树的实现数据结构实验报告

软件学院设计性实验报告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三个文件,以保证系统的通用性。
一、实验目的1、掌握哈夫曼编码原理;2、熟练掌握哈夫曼树的生成方法;3、理解数据编码压缩和译码输出编码的实现。
二、实验要求实现哈夫曼编码和译码的生成算法。
三、实验内容先统计要压缩编码的文件中的字符字母出现的次数,按字符字母和空格出现的概率对其进行哈夫曼编码,然后读入要编码的文件,编码后存入另一个文件;接着再调出编码后的文件,并对其进行译码输出,最后存入另一个文件中。
四、实验原理1、哈夫曼树的定义:假设有n个权值,试构造一颗有n个叶子节点的二叉树,每个叶子带权值为wi,其中树带权路径最小的二叉树成为哈夫曼树或者最优二叉树;2、哈夫曼树的构造:weight为输入的频率数组,把其中的值赋给依次建立的HT Node对象中的data属性,即每一个HT Node对应一个输入的频率。
数据结构哈夫曼树实验报告

数据结构哈夫曼树实验报告一、实验内容本次实验的主要内容是哈夫曼树的创建和编码解码。
二、实验目的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.实验原理2.1 哈夫曼编码哈夫曼编码是一种无损数据压缩算法,通过根据字符出现的频率构建一颗哈夫曼树,将频率较高的字符用较短的编码表示,频率较低的字符用较长的编码表示。
哈夫曼编码的编码表是唯一的,且能够实现前缀编码,即一个编码不是另一个编码的前缀。
2.2 构建哈夫曼树构建哈夫曼树的过程如下:1) 将每个字符及其频率作为一个节点,构建一个节点集合。
2) 每次从节点集合中选择出现频率最低的两个节点,构建一个新节点,并将这两个节点从集合中删除。
3) 将新节点加入节点集合。
4) 重复以上步骤,直到节点集合中只有一个节点,这个节点就是哈夫曼树的根节点。
2.3 编码过程根据哈夫曼树,对每个字符进行编码:1) 从根节点开始,根据左子树为0,右子树为1的规则,将编码依次加入编码表。
2) 对于每个字符,根据编码表获取其编码。
3) 将编码存储起来,得到最终的编码序列。
3.实验步骤3.1 数据读取与统计从输入文件中读取字符序列,并统计各个字符的频率。
3.2 构建哈夫曼树根据字符频率构建哈夫曼树。
3.3 构建编码表根据哈夫曼树,构建每个字符的编码表。
3.4 进行编码根据编码表,对输入的字符序列进行编码。
3.5 进行解码根据哈夫曼树,对编码后的序列进行解码。
4.实验结果与分析4.1 压缩率分析计算原始数据和压缩后数据的比值,分析压缩率。
4.2 编码效率分析测试编码过程所需时间,分析编码效率。
4.3 解码效率分析测试解码过程所需时间,分析解码效率。
4.4 应用场景分析分析哈夫曼编码在实际应用中的优势和适用场景。
5.结论通过本次实验,我们深入了解了哈夫曼编码的原理和实现方法,实践了哈夫曼编码的过程,并对其在数据压缩中的有效性进行了验证。
实验结果表明,哈夫曼编码能够实现较高的压缩率和较高的编解码效率。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
数据结构实验报告实验二Huffman树1、实验目的通过选择下面两个题目之一进行实现,掌握如下内容:➢掌握二叉树基本操作的实现方法➢了解哈夫曼树的思想和相关概念➢学习使用二叉树解决实际问题的能力2、实验内容利用二叉树结构实现哈夫曼编/解码器。
基本要求:1、初始化(Init):能够对输入的任意长度的字符串s进行统计,统计每个字符的频度,并建立赫夫曼树2、建立编码表(CreateTable):利用已经建好的哈夫曼树进行编码,并将每个字符的编码输出。
3、编码(Encoding):根据编码表对输入的字符串进行编码,并将编码后的字符串输出。
4、译码(Decoding):利用已经建好的哈夫曼树对编码后的字符串进行译码,并输出译码结果。
5、打印(Print):以直观的方式打印哈夫曼树(选作)6、计算输入的字符串编码前和编码后的长度,并进行分析,讨论哈夫曼编码的压缩效果。
代码要求:1、必须要有异常处理,比如删除空链表时需要抛出异常;2、保持良好的编程的风格:➢代码段与段之间要有空行和缩近➢标识符名称应该与其代表的意义一致➢函数名之前应该添加注释说明该函数的功能➢关键代码应添加注释说明其功能3、递归程序注意调用的过程,防止栈溢出4、代码中需要标注每一个函数的时间复杂度三、算法思路与主要代码1.设计存储结构1.1 哈夫曼树的结点结构struct HNode //哈夫曼树的结点结构{int weight;//结点权值int parent;//双亲指针int LChild;//左孩子指针int RChild ;//右孩子指针};1.2 编码表结点结构struct HCode //编码表结点结构{char data;char code[100];};1.3哈夫曼树类结构class Huffman //哈夫曼树类结构{private:HNode* HTree;HCode* HCodeTable;char str[1024];char leaf[256];int a[256];void code(int i,string newcode);public:int n;void init();void CreateHtree();void SelectMin(int &x, int &y, int s,int e);void CreateCodeTable();void Encode(char *d);void Decode(char *s, char *d);void print(int i,int m);~Huffman(); //析构函数};2.统计字符串中的字频扫描原始数据,用整型数组变量nNum来记录每一个字符出现的次数当字符没有出现时,对应的nNum[ch]的值为0,可以把读取的字符ch的ASCII码当成,当ch出现时,nNum[ch]自动加一从而统计输入字符串中各个字符数量,获得各个字符出现频率。
//初始化统计字频时间复杂度O(n)具体实现:void Huffman::init(){int nNum[256]= {0};int ch = cin.get();int i=0;while((ch!='\0') && (ch!='\n')){nNum[ch]++;str[i++] = ch;ch = cin.get();}str[i]='\0' ;n = 0;for ( int i=0;i<256;i++){if (nNum[i]>0)//若nNum[i]==0说明该字符未出现{leaf[n] = (char)i;a[n] = nNum[i];n++;}}}3.创建哈夫曼树根据二中所有统计的字符的频度,选择其中的两个权值最小的字符。
构建SelectMin函数,其中X为最小值,Y为次小值是s,e为下标遍历权值表,迭代选择两个最小值。
代码如下://创建哈夫曼树时间复杂度O(n^2)void Huffman::SelectMin(int &x, int &y, int s, int e ){int i;for ( i=s; i<=e;i++)if (HTree[i].parent == -1){x =y= i; break;//找出第一个有效权值x,并令y=x}for ( ; i<e;i++)if (HTree[i].parent == -1)//该权值未使用过{if ( HTree[i].weight< HTree [x].weight){y = x; x = i;//迭代,依次找出前两个最小值}else if ((x==y) || (HTree[i].weight< HTree [y].weight))y = i;//找出第2个有效权值y}}4.打印哈夫曼树参考CSDN论坛,采用凹入表来打印哈夫曼树(根结点空一格直接打印,第2层结点空2格打印,第3 层结点空3格的打印,以此类推,每个节点占用独立的一行。
由于只有叶子结点是有对应字符的,所以其他结点可以打印该结点的权值,采用前序遍历十分)#include<iomanip> //输出格式控制调用iomanip这个库,更改输出格式,实现打印凹入表。
实现如下://打印哈夫曼树#define N 10//定义树的最大深度void Huffman::print(int i, int m){if (HTree[i].LChild == -1)cout<<setfill(' ')<<setw(m+1)<<leaf[i]<<setfill('-')<<setw(N-m)<<'\n';else{cout<<setfill(' ')<<setw(m+1)<<HTree[i].weight<<setfill('-')<<setw(N-m)<<'\n';print(HTree[i] .LChild,m+1);print(HTree[i] .RChild,m+1);}}5.创建编码表采用向上而下的递归处理方式,对每个节点进行编码。
从哈夫曼树的根节点开始,设其编码为空,然后分别对其左右子树中的节点进行编码。
若子树的根节点是其父节点的左子树,则编码为0,若是右子树,则编码为1,然后递归处理。
直到叶子节点为止。
实现如下://创建编码表时间复杂度O(n)void Huffman::code(int i,string newcode) //递归函数,对第i个结点编码{if(HTree[i].LChild==-1)HCodeTable[i].code=new code;return;}code(HTree[i].LChild,newcode+"0");code(HTree[i].RChild,newcode+"1");}void Huffman::CreateCodeTable() //生成编码表{code(2*n-2,"");}6.编码利用4中的编码表,将需要编码的字符串意义读取在表中找到相应的编码代码实现://编码时间复杂度O(n)void Huffman::Encode(char *d){char *s = str;while(*s!='\0'){for (int i=0;i<n;i++)if (*s == HCodeTable[i].data ){strcat(d, HCodeTable[i].code);//d 为编码后的字符串break;}s++;}}7.解码将编码串从左到右逐位判别,直到确定一个字符,即从哈夫曼树根节点出发,根据每一位是0还是1确定是左子树还是右子树,直到到达叶子节点,至此一个字符解码结束,然后从根节点开始解码下一个字符。
代码实现://解码时间复杂度O(n)void Huffman::Decode(char *s,char *d) //s为解码串,d为解码后的字符串{while(*s!='\0')int parent=2*n-2; //根节点在HTree中的下标while(HTree[parent].LChild!=-1) //不是叶子结点时{if(*s=='0')parent=HTree[parent].LChild;elseparent=HTree[parent].RChild;s++;}*d=HCodeTable[parent].data;d++;}}8.主函数测试代码如下://主函数测试int main(){Huffman HFCode;cout<<"请输入要编码的字符串:";HFCode.init();cout<<"创建Huffman 树:"<<endl;void SelectMin();HFCode.print(2*HFCode.n-2,1);cout<<"创建Huffman 编码表:"<<endl;HFCode.CreateCodeTable();char d[1024]={0};HFCode.Encode(d);cout<<"编码结果:"<<d<<endl;char s[1024]={0};HFCode.Decode(d,s); cout<<"解码结果:"<<s<<endl;}四、总结程序写的比较乱,花了好长时间,仍然有点小问题没有调试出来,比较遗憾。
对整体哈夫曼编码(不等长编码)有了更加清晰的了解。
尽管实现的只是字符串编码,实际上无法达到压缩编码的作用,应该是建立在比特上的。
但同时通过这个模拟的哈夫曼编码实现了对二叉树的深入理解,也尝试用它解决一些实际问题。
五、附源码#include<iostream>#include<cstring>#include<iomanip> //输出格式控制using namespace std;struct HNode //哈夫曼树的结点结构{int weight;//结点权值int parent;//双亲指针int LChild;//左孩子指针int RChild ;//右孩子指针};struct HCode //编码表结点结构{char data;char code[100];};class Huffman //哈夫曼树类结构{private:HNode* HTree;HCode* HCodeTable;char str[1024];char leaf[256];int a[256];void code(int i,string newcode);public:int n;void init();void CreateHtree();void SelectMin(int &x, int &y, int s,int e);void CreateCodeTable();void Encode(char *d);void Decode(char *s, char *d);void print(int i,int m);~Huffman();};//初始化统计字频void Huffman::init(){int nNum[256]= {0};int ch = cin.get();int i=0;while((ch!='\0') && (ch!='\n')){nNum[ch]++;str[i++] = ch;ch = cin.get();}str[i]='\0' ;n = 0;for ( int i=0;i<256;i++){if (nNum[i]>0)//若nNum[i]==0说明该字符未出现{leaf[n] = (char)i;a[n] = nNum[i];n++;}}}//创建哈夫曼树void Huffman::SelectMin(int &x, int &y, int s, int e ) {int i;for ( i=s; i<=e;i++)if (HTree[i].parent == -1){x =y= i; break;//找出第一个有效权值x,并令y=x}for ( ; i<e;i++)if (HTree[i].parent == -1)//该权值未使用过{if ( HTree[i].weight< HTree [x].weight){y = x; x = i;//迭代,依次找出前两个最小值}else if ((x==y) || (HTree[i].weight< HTree [y].weight))y = i;//找出第2个有效权值y}}//打印哈夫曼树#define N 10//定义树的最大深度void Huffman::print(int i, int m){if (HTree[i].LChild == -1)cout<<setfill(' ')<<setw(m+1)<<leaf[i]<<setfill('-')<<setw(N-m)<<'\n';else{cout<<setfill(' ')<<setw(m+1)<<HTree[i].weight<<setfill('-')<<setw(N-m)<<'\n'; print(HTree[i] .LChild,m+1);print(HTree[i] .RChild,m+1);}}//创建编码表void Huffman::code(int i,string newcode){if(HTree[i].LChild==-1){HCodeTable[i].code=new code;return;}code(HTree[i].LChild,newcode+"0");code(HTree[i].RChild,newcode+"1");}void Huffman::CreateCodeTable() //生成编码表{code(2*n-2,"");}//编码void Huffman::Encode(char *d){char *s = str;while(*s!='\0'){for (int i=0;i<n;i++)if (*s == HCodeTable[i].data ){strcat(d, HCodeTable[i].code);//d 为编码后的字符串break;}s++;}}//解码void Huffman::Decode(char *s,char *d) //s为解码串,d为解码后的字符串{while(*s!='\0'){int parent=2*n-2; //根节点在HTree中的下标while(HTree[parent].LChild!=-1) //不是叶子结点时{if(*s=='0')parent=HTree[parent].LChild;elseparent=HTree[parent].RChild;s++;}*d=HCodeTable[parent].data;d++;}}//析构函数Huffman:: ~ Huffman(){delete []HTree; delete []HCodeTable;}//主函数测试int main(){Huffman HFCode;cout<<"请输入要编码的字符串:";HFCode.init();cout<<"创建Huffman 树:"<<endl;void SelectMin();HFCode.print(2*HFCode.n-2,1);cout<<"创建Huffman 编码表:"<<endl;HFCode.CreateCodeTable();char d[1024]={0};HFCode.Encode(d);cout<<"编码结果:"<<d<<endl;char s[1024]={0};HFCode.Decode(d,s); cout<<"解码结果:"<<s<<endl; }。