哈夫曼树
written on 2022-06-06
来补一下以前漏学的普及组知识点
Part1 引入
以最经典的二叉哈夫曼树为例。
二叉哈夫曼树,是由对最短二进制编码的研究拓展而来的。
所谓最短二进制编码,描述大致如下:
一部资料中有
种不同的单词,从 到 进行编号。其中第 种单词出现的频率为 。现在要用二进制串 来替换第 种单词,使得其满足如下要求: 对于任意的
, ,都有: 不是 的前缀。 问题即为,如何选择
,才能使压缩以后得到的新的资料长度最小。
改编自P2168 [NOI2015] 荷马史诗
对于这个问题,我们就可以通过构造一棵二叉的 Huffman 树来解决。
part2 构造方法
转化后的问题:对于给定的集合元素个数为
Huffman 算法:
把每一个单词看作一个单结点子树放在一个树的集合中,每棵子树的权值等于相应单词的频率。每次取权值最小的两棵子树合并成为一棵新树,并重新放到集合中。新树的权值即等于两棵子树权值之和。
摘编自刘汝佳的入门紫书。
这也就是转化后的问题的求解方案。
part3 求解方法
主要有两种。
一种是用一个优先队列,直接存取,代码容易实现,时间复杂度
例题:P1090 合并果子
另一种方法是用两个普通队列,一个存的是权值有序的子树,另一个存的是合并后的子树。这种方法中,为了保证 或是基数排序,每次从两个队列分别的前两个元素中,取出较小的两个,合并后插入二号队列,这样同时又可以保证二号队列中的子树权值有序,保证了实现的正确性以及代码效率。
part4 算法正确性证明
这个证明我个人感觉入门紫书的证明不太直观,于是用了另一种更简洁的证明方式。
对于一棵二叉哈夫曼树,初始元素也就是其中的叶子节点,转化后的问题的答案的另一种计算方式,就是该树中非叶子节点的权值之和。
原因的话,因为每一个叶子节点的祖先都是非叶子节点,而每一个非叶子节点的权值就是它的两个子节点的权值之和,于是最底层的答案经过它的所有祖先结点的累加,最终得到的就是其权值乘以深度。
然后,我们根据哈夫曼树的构建过程,可以知道这棵树的总结点个数是
part5 扩展
之前讨论的都是二叉哈夫曼树,显然如果用
例题:P2168 荷马史诗
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!