我想实现具有以下约束的双端优先级队列:
需要在固定大小的数组中实现。包含100个元素..如果需要在数组填满后添加新元素,则需要删除最旧元素
在O(1)
如果可能,请插入O(1)
如果可能,请删除O(1)
如果可能,在O(1)中清除为空/初始状态
O(1)
我希望O(1)用于所有上述5个操作,但是在同一个实现中它们不可能在所有这些操作上都有O(1)。 Atleast O(1)关于3次操作,O(log(n))关于其他2次操作就足够了。
如果可以为这样的实现提供任何指针,我们将不胜感激。
答案 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是固定的,所以你真正想要的是一个对给定数据集来说很快的算法。可能两个并行的传统堆优先级队列很好(一个用于高,一个用于低)。
如果您对自己拥有的数据有了更多了解,那么您可能会做出更特殊的目的。