一尘不染

空间有限的优先级队列:寻找一个好的算法

algorithm

这不是功课。

我正在使用一个小的“优先级队列”(此刻已实现为数组)来存储最后N个具有 最小值的
项目。这有点慢-O(N)项插入时间。当前的实现会跟踪数组中最大的项目,并丢弃所有不适合数组的项目,但是我仍然想进一步减少操作数。

寻找符合以下要求的优先级队列算法:

  1. 队列可以实现为数组,具有固定的大小并且不能增长。严格禁止在任何队列操作期间进行动态内存分配。
  2. 任何不适合数组的内容都将被丢弃,但是队列保留了所有遇到的最小元素。
  3. O(log(N))插入时间(即,将元素添加到队列中应占用O(log(N)))。
  4. (可选)对队列中最大项的O(1)访问(队列存储最小项目,因此最大的项将首先被丢弃,我将需要它们以减少操作数)
  5. 易于实施/理解。理想情况下-与二进制搜索类似-一旦您理解它,便会永远记住它。
  6. 元素不需要以任何方式排序。我只需要保持N遇到的最小值即可。当我需要它们时,我将立即访问所有它们。因此,从技术上讲,它不必是队列,我只需要存储N个最后的最小值即可。

我最初考虑使用二进制堆(可以很容易地通过数组实现),但是当数组不再增长时,它们显然表现不佳。链接列表和数组将需要额外的时间来移动内容。stl优先级队列增长并使用动态分配(不过,我
可能 对此有误)。

那么,还有其他想法吗?

-编辑-
我对STL实施不感兴趣。由于大量的函数调用,STL实现(由少数人建议)比当前使用的线性数组慢一些。

我对优先级队列 算法 感兴趣,而不是强制性。


阅读 210

收藏
2020-07-28

共1个答案

一尘不染

基于数组的堆似乎很适合您的目的。我不确定你为什么拒绝他们。

您使用最大堆。

假设您有一个N元素堆(实现为数组),其中包含到目前为止所见的N个最小元素。

当元素进入时,请检查最大时间(O(1)时间),如果大于则拒绝。

如果输入的值较低,则将根修改为新值,然后向下筛选该更改的值-最坏的情况是O(log N)时间。

筛选过程很简单:从根开始,在每个步骤中,您都用它的较大子项交换此值,直到恢复max-heap属性。

因此, 如果使用std :: priority_queue,则不必进行任何可能必须 删除的操作 。根据std ::
priority_queue的实现,这可能导致内存分配/重新分配。

因此,您可以拥有如下代码:

  • 大小为N的已分配数组。
  • 用您看到的前N个元素填充它。
  • heapify(您应该在标准教科书中找到它,它使用sift-down)。这是O(N)。
  • 现在,您得到的任何新元素都可以在O(1)时间内拒绝它,或者在最坏的情况下通过筛选O(logN)时间来插入。

但是,平均而言,您可能不必完全筛选新值,并且可能会比O(logn)平均插入时间更好(尽管我尚未尝试证明)。

您只分配一次大小为N的数组,并且任何插入都是通过交换数组的元素来完成的,因此此后没有动态内存分配。

请查看Wiki页面,该页面具有用于heapify和sift-
down的伪代码:http :
//en.wikipedia.org/wiki/Heapsort

2020-07-28