浅谈Huffman树
所谓Huffman树,就是叶子结点带权的\(K\)叉树,假设每个叶子的权值为\(v\),到根的距离为\(dep\),那么最小化\(\sum v_i*dep_i\)就是\(Huffman\)树的拿手好戏。
为了最小化这个值,显然我们应该尽量让权值大的叶子深度浅,合并果子就是一个典型\(2\)叉\(Huffman\)树问题。
那么对于\(k\)叉\(Huffman\)树呢?
我们以\(3\)叉\(Huffman\)树为例,有这么\(6\)个数:\(1,2,3,5,8,9\)
按照合并果子这题的思路,我们应该先花\(6\)体力合并\(1,2,3\),新序列为:\(6,5,8,9\)
然后花\(19\)体力合并\(5,6,8\),新序列为:\(19,9\)
最后花\(28\)体力合并\(19,9\),新序列是\(28\),一共用的体力为\(53\)
但是我们换一种方式合并:
\(1,2,3,5,8,9\)
\(3,3,5,8,9\)
\(11,8,9\)
\(28\)
一共用了\(42\)体力。
那么问题就出现了,显然对于\(2\)叉\(Huffman\)树的贪心策略不再适用于\(k\)叉\(Huffman\)树。
但是,是真的不适用么?
仔细考虑上面两个例子,在用了\(53\)体力的例子里,我们最后一步合并了\(19,9\),但其实我们还可以假设有一个权值为\(0\)的点在这一步被合并了。
但在用了\(42\)体力的例子里,我们第一步就把权值\(0\)给安排了。
所以对于\(2\)叉\(Huffman\)树的贪心策略还是有用的,不过我们忽视了权值为\(0\)的结点。因为\(2\)叉\(Huffman\)树怎么建都不会存在某一步被合并的结点少于\(2\),但是\(k\)叉\(Huffman\)树不一样,它必须满足\((n-1)mod(k-1)=0\)才会每一步合并的结点都不少于\(k\)。因为每次合并都会减少\(k-1\)个结点,一共会减少\(n-1\)个结点。如果不满足上述等式,我们只需要不断添加权值为\(0\)的结点直到它满足为止即可。
关于\(k\)叉\(Huffman\)树的建立,也可以按照合并果子一样用堆辅助即可。