我无法从霍夫曼树中正确弹出。现在我正在创建一个基于minheap的霍夫曼树,我想做以下事情:
如果我们假设A和B是两个不同的子树,我会说如果A的频率小于B的频率,A将首先弹出。 如果它们具有相同的频率,那么我会在任何A的叶节点中找到ASCII值中的最小字符。然后我会看到A中的最小字符叶子节点是否小于B的叶子节点中的任何一个。如果是这样的话,我会在B之前弹出A。如果不是,我会弹出B。< - 这就是我遇到的麻烦。
例如:
我们假设我输入:
eeffgghh\n (every letter except for \n's frequency which is 1 is 2)
进入我的霍夫曼树。然后我的树看起来像这样:
9
/ \
5 4
/ \ / \
3 h g f
/\
e \n
下面是我试图弹出我的霍夫曼minheap。如果两个字母的频率相同,我在比较时遇到问题。如果有人可以提供帮助,那就太好了。谢谢!
void minHeap::heapDown(int index)
{
HuffmanNode *t = new HuffmanNode();
if(arr[index]->getFreq() == arr[left]->getFreq() || arr[index]->getFreq() == arr[right]->getFreq()) //arr is an array of HeapNodes
{
if(arr[left]->getLetter() < arr[right]->getLetter())
{
t = arr[index]; //equals operator is overloaded for swapping
arr[index] = arr[left];
arr[left] = t;
heapDown(left);
}
else
{
t = arr[index];
arr[index] = arr[right];
arr[right] = t;
heapDown(right);
}
}
if(arr[index]->getFreq() > arr[left]->getFreq() || arr[index]->getFreq() > arr[right]->getFreq())
{
if(arr[left]->getFreq() < arr[right]->getFreq())
{
t = arr[index];
arr[index] = arr[left];
arr[left] = t;
heapDown(left);
}
else
{
t = arr[index];
arr[index] = arr[right];
arr[right] = t;
heapDown(right);
}//else
}//if
}
答案 0 :(得分:1)
标准C ++库包含堆算法。除非您不被允许使用它,否则您可能会发现它更容易。
标准C ++库还包含swap(a,b),它比你正在进行的交换更具可读性。然而,在heapDown中交换是低效的:你应该做的是保持元素放置在一个临时的,然后筛选孩子,直到你找到一个放置元素的地方,然后把它放在那里。
如果您实现了运算符&lt;
您的代码也将更具可读性。对于HuffmanNode。无论如何,你进行的比较是必要的;你真正想做的是(遗漏很多细节):
heapDown(int index, Node* value) {
int left = 2 * min - 1; // (where do you do this in your code???)
// It's not this simple because you have to check if left and right both exist
min = *array[left] < *array[left + 1] ? left : left + 1; // 1 comparison
if (array[min] < to_place) {
array[index] = array[min];
heapDown(min, value);
} else {
array[index] = value;
}
你的第一次比较(第三行)是完全错误的。 a == b || a == c并不意味着b == c,或者确实给你任何关于b和c中哪一个更少的信息。仅对b和c进行第二次比较通常会给出错误的答案。
最后,您在每次调用时都会不必要地执行new
,但从不执行delete
。所以你慢慢地,无情地泄露了记忆。