最小堆中大于或等于 x 的第 K 个最小元素

Kth smallest element greater than or equal to x in a min heap

我这里有 Skiena 手册中的代码:

int heap_compare(priority_queue *q, int i, int count, int x)
{
  if ((count <= 0) || (i > q->n)) return(count);

  if (q->q[i] < x) {
    count = heap_compare(q, pq_young_child(i), count-1, x);
    count = heap_compare(q, pq_young_child(i)+1, count, x);
  }

  return(count);
}

我不明白为什么计数是而不是为节点的右子节点递减?

计数不会减少,因为当您向右子树移动时,当前节点被计为 "k-1" 较小元素之一,而当我们向左移动时,当前节点不包含在 "k" 最小的元素。

我同意@Bugaboo 的观点,这里的代码有点误导,尽管接受的答案确实提供了合理的解释。

我找到了解决方案here 提供了更清晰的解释。一旦节点本身与 x 进行比较,计数器就会更新,然后算法移动 伪代码来自@Saeed Amiri:

% determine if the k-th smallest element in a min-heap is less than a given number x
void CheckNode(Node node,int k, int x, ref int counter)
{
    if (node.value > x)
    {
        counter++;
        if (counter >= k)
            return;

        CheckNode(node.Left, k, x, ref counter);
        CheckNode(node.Right,k, x, ref counter);
    }
}

count 未更新,因为它已针对当前节点递减一次,并且该值已传递到左节点的 heap_compare 方法中。并且从左节点的 heap_compare 返回的值分配给 count 所以不需要再次递减。它可以重写如下。

int heap_compare(priority_queue *q, int i, int count, int x)
{
  if ((count <= 0) || (i > q->n)) return(count);

  if (q->q[i] < x) {
    count = count-1;
    count = heap_compare(q, pq_young_child(i), count, x);
    count = heap_compare(q, pq_young_child(i)+1, count, x);
  }

  return(count);
}