所谓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)树的建立,也可以按照合并果子一样用堆辅助即可。