template<class T>
void huffman(MinHeap<TreeNode<T>*> heap, int n)
{
for(int i=0;i<n-1;i++)
{
TreeNode<T> *first = heap.pop();
TreeNode<T> *second = heap.pop();
TreeNode<T> *bt = new BinaryTreeNode<T>(first, second, first.data, second.data);
heap.push(bt);
}
}
在我的Fundamentals of Data Structures in C++教科书中,它给出了霍夫曼编码的2页定义,以及上面的代码。对我来说,这本书不够详细,所以我已经完成了谷歌搜索,我学会了霍夫曼编码的过程。教科书声称在上面的代码末尾,制作了霍夫曼树。但对我来说这似乎是错误的,因为霍夫曼树不一定是完整的树,但由于heap.push()
,上面的代码似乎总是给出一个完整的树。那么有人可以向我解释这段代码是如何没有错的吗?
答案 0 :(得分:5)
堆的树结构不一定与得到的霍夫曼树匹配 - 相反,堆包含部分霍夫曼树的森林,最初每个树由单个符号节点组成。然后,循环重复获取具有最小权重的两个节点,将它们组合成一个节点,并将得到的组合节点放回。在进程结束时,堆包含一个完成的树。
答案 1 :(得分:0)
霍夫曼编码的工作原理是在每一步中取两个最低值的项目。当您第一次调用该函数时(因为您的MinHeap按值排序),弹出两个最低值的项并“合并”到一个决策节点中,然后将该节点放回堆中。该节点按其子分数的总和进行评分并放回堆中。将其插回堆中会根据其得分将其放入正确的位置;如果它仍然低于任何其他项目,它将是第一个,否则它将在其他地方。
所以这个算法是从下到上构建树,当你清空堆时,你将拥有一个完整的树。但我不明白'n'是什么意思;循环应该是while (heap.size() > 1)
。无论如何,树不是“满”,不同的分支将根据初始堆中项目的频率得分而有不同的长度。