【殷人昆数据结构】第五章5.6 哈夫曼树Huffman代码的调试

哈夫曼树是一种特殊的二叉树,通过最小化带权路径长度(WPL)提高编码效率。文章介绍了哈夫曼树的构造过程,通过合并权值最小的树节点来构建新的树,并探讨了其在数据压缩和编码中的应用。同时,提供了相关函数如HuffmanNode和HuffmanTree的定义与操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

哈夫曼树Huffman


概念:路径长度
两个结点之间的路径长度 PL 是连接两结点的路径上的分支数。
树的外部路径长度是各叶结点(外结点)到根结点的路径长度之和 EPL。
树的内部路径长度是各非叶结点(内结点)到根结点的路径长度之和 IPL。
树的路径长度 PL = EPL + IPL。
n 个结点的二叉树的路径长度不小于下述数列前 n 项的和,即

P L = ∑ i = 1 n l o g 2 i PL = \sum_{i=1}^n log_2i PL=i=1nlog2i

= 0 + 1 + 1 + 2 + 2 + 2 + 2 + 3 + 3 + . . . =0+1+1+2+2+2+2+3+3+... =0+1+1+2+2+2+2+3+3+...
其路径长度最小者为
P L = ∑ i = 1 n l o g 2 i PL = \sum_{i=1}^n log_2i PL=i=1nlog2i
完全二叉树或理想平衡树满足这个要求。

概念:带权路径长度(Weighted Path Length,WPL)
在很多应用问题中为树的叶结点赋予一个权值,用于表示出现频度、概率值等。因此,在问题处理中把叶结点定义得不同于非叶结点,把叶结点看成“外结点”,非叶结点看成“内结点”。这样的二叉树称为扩充二叉树。
扩充二叉树中只有度为 2 的内结点和度为 0的外结点。根据二叉树的性质,有n个外结点就有n-1个内结点,总结点数为2n-1。(这是在全部内结点度为二的情况下)
若一棵扩充二叉树有 n 个外结点,第 i 个外结点的权值为wi,它到根的路径长度为li,则该外结点到根的带权路径长度为wi*li。
扩充二叉树的带权路径长度定义为树的各外结点到根的带权路径长度之和。

W P L = ∑ i = 1 n w i × l i WPL=\sum_{i=1}^nw_i\times l_i WPL=i=1nwi×li

对于同样一组权值,如果放在外结点上,组织方式不同,带权路径长度也不同。带权路径长度达到最小的扩充二叉树即为Huffman树。
在Huffman树中,权值大的结点离根最近。

由给定 n 个权值 {w0, w1, w2, …, wn-1},构造 具有 n 棵扩充二叉树的森林 F = { T0, T1, T2, …, Tn-1 },其中每棵扩充二叉树 Ti 只有一个带权值 wi 的根结点, 其左、右子树均为空。

重复以下步骤, 直到 F 中仅剩一棵树为止:
在 F 中选取两棵根结点的权值最小的扩充二叉树, 做为左、右子树构造一棵新的二叉树。置新的二叉树的根结点的权值为其左、右子树上根结点的权值之和。
在 F 中删去这两棵二叉树。
把新的二叉树加入 F。

哈夫曼树的作用

不同的编码方式对于存储空间及编码效率有着巨大影响,我们常用“带权的路径长度”来表示编码效率。比如编码一篇文章,最常见的文字与非常不常见的文字如果采用相同位数的编码,会降低运行效率。所以,一般出现频率较高的文字采用较少位数进行编码,出现频率较低的文字采用较高位数进行编码。我们用权值来表示一个数出现的频率,用以上构造方法来将每个文字构造成哈夫曼树的叶结点,从跟结点往下左子树连线上为0,右子树为1,以此方式进行编码。

主函数

#include <fstream>
#include <cassert>
#include "HuffmanTree.h"
#include "MinHeap.h"
using namespace std;
int main(){
   
	ifstream fin("data.txt");
	assert(fin);
	int n,i;
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值