从Huffman Tree Min Heap中弹出/删除节点

时间:2012-11-30 10:43:25

标签: c++ algorithm data-structures huffman-code min-heap

我无法从霍夫曼树中正确弹出。现在我正在创建一个基于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
}

1 个答案:

答案 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。所以你慢慢地,无情地泄露了记忆。