我正在寻找一种有效的数据结构来表示优先级列表。具体来说,我需要为一组项目分配优先级,并仅返回最高评分项目。我已经查看了优先级排队,但这些队列似乎并不适合我的需求。一旦我从队列中轮询最高评级项目,他们就会重新组织堆结构。
最简单的解决方案当然是链表,在最坏的情况下,插入操作需要很长时间。
有没有人有更好的解决方案?
答案 0 :(得分:4)
嗯。 Skip lists?它们应该有O(log n)插入(作为基于堆的队列)但是获得顶部元素应该是O(1)[包括删除它]。它们甚至可以使用无锁算法实现。
答案 1 :(得分:4)
如果您只需要 k 顶级项目而从不需要查看其他项目,您可以使用仅存储当前顶部的简单链接列表或数组< em> k 项目,加上一个数字(列表中元素的最差分数)。
在Add()
操作中,您只需将项目与列表中的最差值进行比较,如果更好,则将当前最差项与添加项进行交换。这会在最坏情况中占用 O(k)时间,因为您需要找到当前得分最低的元素。然而,平均情况是 O(1),因为当你向列表中添加更好的元素时,必须进行交换的概率趋向于0(也就是说,你不是实际上添加任何项目。)
因此,如果您随机生成元素,那么您的表现可能非常好。即使您生成有序的项目(最坏情况),它也可能足够快,您的 k 值。
答案 2 :(得分:4)
堆似乎非常合适,看起来你错了。
假设您想要前x个元素(这个x与n,btw相比如何?)
您正在做的是将所有内容放入最大堆并获得顶部x。
我建议你使用精确x个元素的最小堆。
您插入堆中的第一个x元素。
下一个传入元素,您可以与堆中的min进行比较,这可以非常快速地完成(O(1)时间)。如果更小,则只需忽略传入元素。
如果传入元素大于min,则将min增加到传入元素并在堆中将其向下移动。这应该是最差的logx时间。
完成后(在nlogx时间内),您可以在O(xlogx)时间内按排序顺序从堆中检索元素。
根据数据的方式(以及x的小小),使用这种最小堆解决方案可能非常快。
如果您真的希望插入速度超快且不关心检索,那么您也可以执行以下操作。
按照它们的顺序将元素插入到一个向量(具有分摊的O(1)插入时间的数组中)。
使用Selection算法查找第x个最大元素(在O(n)时间内,但常量可能很大)。假设这个数字是S.
现在遍历数组,将每个元素与S进行比较,并选择与S一样大的元素。
如果x的大小合理且与n相当(如n / 2或其他东西),这可能会很好,但如果x与n相比较小,我建议使用min-heap。
答案 3 :(得分:1)
JDK有一个内置的pqueue类(java.util.PriorityQueue),它基于堆算法。
抱歉,我只是看到了关于堆不符合您需求的信息。你能解释一下原因吗?您可以编写自定义比较器(或使您的商品具有可比性),PriorityQueue将适当地订购您的商品。