实现双端优先级队列的最佳方法是什么?

时间:2013-07-09 19:54:13

标签: algorithm data-structures big-o priority-queue heapsort

我想实现具有以下约束的双端优先级队列:

  • 需要在固定大小的数组中实现。包含100个元素..如果需要在数组填满后添加新元素,则需要删除最旧元素

  • 在O(1)

  • 中需要最大值和最小值
  • 如果可能,请插入O(1)

  • 如果可能,请删除O(1)

  • 中的最小值
  • 如果可能,在O(1)中清除为空/初始状态

  • O(1)

  • 中当前数组中元素数的计数

我希望O(1)用于所有上述5个操作,但是在同一个实现中它们不可能在所有这些操作上都有O(1)。 Atleast O(1)关于3次操作,O(log(n))关于其他2次操作就足够了。

如果可以为这样的实现提供任何指针,我们将不胜感激。

4 个答案:

答案 0 :(得分:4)

有许多专门的数据结构。一个简单的数据结构是最小 - 最大堆,它实现为二进制堆,其中层在“最小层”(每个节点小于或等于其后代)和“最大层”(每个节点大于或者等于它的后代。)最小值和最大值可以在时间O(1)中找到,并且,如在标准二进制堆中,排队和出队可以在每个时间O(log n)时间内完成。

您还可以使用interval heap data structure,这是该任务的另一个专用优先级队列。

或者,您可以使用两个优先级队列 - 一个按升序存储元素,另一个按降序存储。无论何时插入值,都可以将元素插入到两个优先级队列中,并使每个元素存储指向另一个的指针。然后,无论何时将min或max出列,都可以从其他堆中删除相应的元素。

作为另一种选择,您可以使用平衡二叉搜索树来存储元素。然后可以在时间O(log n)中找到最小值和最大值(如果缓存结果,则为O(1)),并且可以在时间O(log n)中完成插入和删除。如果您使用的是C ++,则只需使用std::map,然后使用begin()rbegin()分别获取最小值和最大值。

希望这有帮助!

答案 1 :(得分:2)

binary heap会在O(log n)O(1)中为其他人提供插入和删除最小值。

唯一棘手的部分是在阵列装满后删除最旧的元素。为此,请保留另一个数组:

time[i] = at what position in the heap array is the element 
          added at time i + 100 * k. 

每100次迭代,您递增k

然后,当阵列第一次填满时,你移除heap[ time[0] ],当它第二次填满heap[ time[1] ]时填充......,当它填满第100次时时间,你回绕并再次删除heap[ time[0] ]等。当它填满k时,你删除heap[ time[k % 100] ](100是你的数组大小)。

确保在插入和删除元素时也更新time数组。

如果你知道它的位置,可以在O(log n)中删除任意元素:只需将它与堆数组中的最后一个元素交换,然后筛选你交换过的元素。

答案 2 :(得分:0)

如果你绝对需要max和min为O(1)那么你可以做的是创建一个链表,你不断跟踪最小值,最大值和大小,然后将所有节点链接到某种类型树结构,可能是一堆。最小值,最大值和大小都是常量,并且由于找到任何节点都在O(log n)中,因此插入和删除都是log n。清算将是微不足道的。

答案 3 :(得分:-1)

如果您的队列是固定大小,那么O符号是没有意义的。任何O(log n)或甚至O(n)操作本质上都是O(1),因为n是固定的,所以你真正想要的是一个对给定数据集来说很快的算法。可能两个并行的传统堆优先级队列很好(一个用于高,一个用于低)。

如果您对自己拥有的数据有了更多了解,那么您可能会做出更特殊的目的。