当前位置: 首页 > 知识库问答 >
问题:

从Huffman Tree Minheap中弹出/删除节点

亢雅懿
2023-03-14

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

李文轩
2023-03-14

标准C库包含堆html" target="_blank">算法。除非您不被允许使用它,否则您很可能会发现它更容易。

标准C库还包含交换(a, b),它比您正在进行的交换更具可读性。然而,heapDown中的交换效率低下:您应该做的是保留要放置在临时元素中的元素,然后向下筛选子元素,直到找到放置元素的位置,然后将其放置在那里。

如果实现了运算符,代码的可读性也会大大提高

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进行第二次比较通常会给出错误的答案。

最后,您在每次调用时都会执行一个不必要的新操作,但从不执行删除操作。所以你正在缓慢但无情地泄漏内存。

 类似资料:
  • 当我通过GPS移除一个节点时,当我试图打印二叉树时,会出现堆栈溢出。下面是我的一些代码。我不能理解它将如何工作良好,如果我删除的名称,但不是,如果我删除的坐标,因为我正在使用相同的删除方法。 我得到的确切错误是“Exe:0xC00000FD中0x013214D6处的未处理异常:堆栈溢出(参数:0x00000001,0x00152FFC)”。在按坐标删除后,在打印函数中会出现这种情况,但如果按名称删

  • 我们能做得更好吗?有没有更好的数据结构可以提供更好的运行时?

  • 我遵循此处的指南从firebase数据库中删除值。这是我的数据结构。 这是我正在使用的代码。 发生的情况是,在这个调用中删除了整个/bookmarks节点,而不仅仅是对所需书签的引用。如何实现只删除一个书签而不是删除整个节点?

  • 如何从控制台从FireBase中删除节点?由于它太大,显然我无法从控制台中删除它。通常我可以按节点名称附近的删除按钮,但它显示控制台仅出于性能原因而读取。

  • 我试图从基于阉羊的双链表中删除一个元素,该列表中的节点满足返回bool的函数。由于某种原因,替换节点的前一个指针(下一个被删除)不更新,而是引用回它自己。 我的代码 测试结果

  • 我有一些脚本,产生与颜色输出,我需要删除ANSI代码。 输出为(在日志文件中): 我不知道如何把ESC字符放在这里,所以我把放在它的位置。 我把剧本改成: 但是现在它给我(在日志文件中): 我怎样才能删除这个'? 也许有一种方法可以完全禁用整个脚本的着色?