查找数组 min-heap 中所有小于 x 的键

发布于 2024-09-28 04:41:36 字数 96 浏览 3 评论 0原文

有人可以描述一种在最小堆的数组实现中找到所有小于 x 的键的算法吗? 我希望运行时间至少为 O(k),其中 k 是报告的键数。

我已经为此摸不着头脑有一段时间了。

Can some one describe an algorithm that finds all keys smaller than x in an array implementation of a min-heap.
I want the running time to be at least O(k) where k is the number of keys reported.

I've been scratching my head for a while now with this.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

夜声 2024-10-05 04:41:37

对于树最小堆有一个简单的递归算法:

void smaller_than(Node *node, int x)
{
    if (node->value >= x)
    {
        /* Skip this node and its descendants, as they are all >= x . */
        return;
    }

    printf("%d\n", node->value);

    if (node->left != NULL)
        smaller_than(node->left, x);
    if (node->right != NULL)
        smaller_than(node->right, x);
}

如果子树的根具有大于或等于 x 的值,那么根据最小堆的定义,其所有后代也将具有大于或等于 x 的值等于x。该算法不需要比其遍历的项目更深入地探索,因此它是 O(k)。

当然,将其转换为数组算法是一件微不足道的事情:

#define ROOT       0
#define LEFT(pos)  ((pos)*2 + 1)
#define RIGHT(pos) ((pos)*2 + 2)

void smaller_than(int x, int pos, int heap[], int count)
{
    /* Make sure item exists */
    if (pos >= count)
        return;

    if (heap[pos] >= x)
    {
        /* Skip this node and its descendants, as they are all >= x . */
        return;
    }

    printf("%d\n", heap[pos]);

    smaller_than(x, LEFT(pos), heap, count);
    smaller_than(x, RIGHT(pos), heap, count);
}

There is a simple recursive algorithm for a tree min-heap:

void smaller_than(Node *node, int x)
{
    if (node->value >= x)
    {
        /* Skip this node and its descendants, as they are all >= x . */
        return;
    }

    printf("%d\n", node->value);

    if (node->left != NULL)
        smaller_than(node->left, x);
    if (node->right != NULL)
        smaller_than(node->right, x);
}

If a subtree's root has a value that is greater than or equal to x, then, by definition of a min-heap, all of its descendants will also have values greater than or equal to x. The algorithm need not explore deeper than the items its traversing, hence it is O(k).

Of course, it's a trivial matter translating this to an array algorithm:

#define ROOT       0
#define LEFT(pos)  ((pos)*2 + 1)
#define RIGHT(pos) ((pos)*2 + 2)

void smaller_than(int x, int pos, int heap[], int count)
{
    /* Make sure item exists */
    if (pos >= count)
        return;

    if (heap[pos] >= x)
    {
        /* Skip this node and its descendants, as they are all >= x . */
        return;
    }

    printf("%d\n", heap[pos]);

    smaller_than(x, LEFT(pos), heap, count);
    smaller_than(x, RIGHT(pos), heap, count);
}
倒带 2024-10-05 04:41:37

要获得“至少”某事物的运行时间并不那么困难,我认为您的意思是“最多”。

不幸的是,最小堆除了最小值之外不太擅长查找其他值。

您可以对堆的树视图进行宽度优先深度优先扫描,并终止到达X的每个分支。这将是O(k),但很复杂。

要找到 Y <= X 的所有 Y,您不妨扫描整个数组,这将是 O(n),但开销要少得多。

选择取决于 n/k 比率

To get a running time of 'at least' something is not so difficult, I assume you mean 'at most'.

Unfortunately, a min-heap is not very good at finding anything else than the smallest value.

You can do a breadth-first depth-first scan of the tree-view of your heap, and terminate every branch where you have reached X. This will be O(k), but complicated.

To find all Y where Y <= X you might as well scan the entire array, this will be O(n) but with much less overhead.

The choice depends on the ratio n/k

空城缀染半城烟沙 2024-10-05 04:41:37

作为数组的实现是无关紧要的,您仍然可以进行自上而下的树搜索。只是不需要使用“经典”指针,您需要计算相应的子节点索引。

这样就可以从顶部开始递归搜索,并在当前节点大于 x 的每个分支上停止递归。这通常会删除许多您不需要检查的值。

对于 k 个返回值,O(k) 显然是最好的情况。如果您的顶部节点 <= x,您将立即开始获得结果。如果它更大,则完成 - 结果为空。

从那里你可以得到子树一直向下的结果,直到你到达值>的分支。 x。您最多需要执行 2*k 检查来修剪这些分支,所以在我看来总共是 O(k) 。

The implementation as array is irrelevant, you can still do a top-down tree-search. Just instead of using the "classic" pointers, you need to calculate the respective child-node indexes.

With that out of the way do a recursive search from the top and stop recursing on each branch where the current node is greater than x. That will in general prune away a lot of values you don't need to check.

With k return values O(k) is obviously your best case. If your top node is <= x, you start getting results right away. If its greater, you are done - the result is empty.

From there you get results all the way down the subtree until you hit branches with values > x. You need to do at most 2*k Checks to prune those branches, so it looks like O(k) in total to me.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文