码迷,mamicode.com
首页 > 其他好文 > 详细

哈夫曼树

时间:2020-06-29 22:37:44      阅读:47      评论:0      收藏:0      [点我收藏+]

标签:存在   lin   需要   个数   队列   lock   可变   条件   sort   

数论 哈夫曼树

1.0 引子

A: 欸,你听说过“带权最优二叉树”嘛?就是“带权路径长度最短的二叉树“嘛?就是“路径上的分支个数称为路径长度”嘛?就是“叶子结点都有一定的权值”嘛?

B: 说人话

A: 《合并果子》..

1.1 二叉哈夫曼算法

也许算法并不叫这个名字,只是我觉得好记好懂就这么叫了..

二叉哈夫曼算法解决的问题与《合并果子》别无二致,但是为了严谨,还是重新叙述一遍二叉哈夫曼算法解决的问题:

有n个数;每一次合并操作代价为两个数字之和;每一次合并可以将两个数字合并为一个数字,其大小为原先两数字之和;试求最小合并代价

一个\(O(nlogn)\)的优先队列解法很快浮现了出来。二叉哈夫曼算法复杂度与该解法同级,但没有利用到优先队列这个数据结构。

一、 开两个数组记为a[],和b[]。a[]数组初始化为升序的原数组,而b[]数组为空

二、 每一次尝试从a[]和b[]队首中找最小的两个数

三、 将其合并之后,放入b[]的队尾

技术图片

1) a[]的单调性保证:初始化时排序,之后不再发生插入操作

2) b[]的单调性保证:每一次合并的结果将会越来越大,而越靠后的合并结果将会插在b[]越靠后的位置上,单调性得到保证

a[]和b[]都有单调性保证,只要从两个队列队首抽一个较小值,即可得到全局最小值

1.2 k叉哈夫曼算法

解决了二叉哈夫曼算法,不禁联想到将情况扩展到更高维的情况:假如同时允许合并k个数字呢?

事实上情况并没有变得太过复杂,优先队列解法可以很轻松的转移过来,同理“k叉哈夫曼算法”诞生了。与二叉哈夫曼算法几乎没有区别,只是每一次取前k小即可。

但是,每一次合并将会减少(k-1)个数字,假如最后一次合并没能凑齐k个数字呢?贪心地考虑一下,越靠后的合并操作,牵扯到的数字越多,因此合并操作越靠后,越应当凑齐正好k个数字,不能浪费机会。由于算法很明显是不能倒序进行的,因此我们只需要事先给数列添加一些人畜无害的"0"调整个数,便能保证最后一次合并可以凑齐k个数字整

虽然具体放"0"的个数很简单,做题的时候顺手推一下就能推出来,但是还是总结了以下公式:

\[(k-(n\mod (k-1)))\mod (k-1) \]

例题:hdu 5884 Sort

一道裸的哈夫曼算法

2.1 哈夫曼树

哈夫曼树其实就是把在进行哈夫曼算法的同时,将k个受牵连的节点抽出来,新建一个点连向这k个节点。脑补一下,就能想象出这么做的后果是会形成一棵树吧..

e.p. 合并 {1,1,2,2} 的哈夫曼树

技术图片

3.1 哈夫曼编码

哈夫曼编码的几条性质:

  1. 哈夫曼编码是一种可变字长编码,即每一个对应元素的编码长度不一定相同
  2. 哈夫曼编码是一种前缀编码,即一组编码中任一编码都不是其他任何一个编码的前缀
  3. 满足同等条件下,哈夫曼编码可以保证利用编码转译后,译文总长度最短

3.2 带权路径

先下一条定义:

带权路径:对于一条从根节点到叶节点的路径,其贡献等于叶节点的点权\(\times\)路径长度(所有边的长度为1)

一个常见的问题就是“带权路径和最小”。其实很好解决,由于在带权路径中叶节点的点权被扩大了路径长度次,那我们就将这些贡献原样的“分摊”给路径上的每一个节点。

容易发现,新的树其实就是哈夫曼树,“带权路径和最小”其实就可以利用哈夫曼算法得到解决

问题的解决

将问题整理一下:有n个k进制密钥,每一个密钥之间长度可以不等;第i个密钥出现了给定的a_i次;密钥之间彼此直接无歧义,即彼此间不是彼此的前缀;试问译文的最短长度

对于k进制密钥,就建一颗k叉树;将n个密钥出现次数作为a_i作为树的叶节点;除叶节点外的节点点权大小为该节点子节点的点权之和。

将每一个节点连向儿子的边顺序编号。由于是k叉树,因此标号大小严格不大于k,因此从根节点到叶节点的路径对应着一个长度为路径长度的k进制密钥,且密钥唯一,彼此不存在覆盖关系,也就不存在前缀关系。

将密钥问题转换为树上的路径问题后,原问题中“译文总长度最短”也就转换为了“带权路径”最短的问题。这便是哈夫曼树所解决的问题。

例题:[NOI2015]荷马史诗](https://www.luogu.org/problem/P2168)

子问题一就是哈夫曼编码的应用:对于子问题二,只需要略改哈夫曼算法:倘若两个队首数字相同,娶一个深度较小的即可

NOI水题一发AC祭 [ヾ(≧▽≦)o ](https://www.luogu.org/record/22383511)

哈夫曼树

标签:存在   lin   需要   个数   队列   lock   可变   条件   sort   

原文地址:https://www.cnblogs.com/ticmis/p/13210714.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!