我需要一个数据结构,它总是保存到目前为止插入的n
个最大项目(没有特定的顺序)。
因此,如果n
为3,我们可以进行以下会话,其中插入一些数字并且容器的内容发生变化:
[] // now insert 1
[1] // now insert 0
[1,0] // now insert 4
[1,0,4] // now insert 3
[1,4,3] // now insert 0
[1,4,3] // now insert 3
[4,3,3]
你明白了。数据结构的名称是什么?实现这个的最佳方法是什么?或者这是在某个图书馆吗?
我正在考虑使用一个容器,其元素(委托)具有priority_queue
,它使用反向比较,因此pop
将删除最小的元素。因此insert
函数首先检查要插入的新元素是否大于最小元素。如果是这样,我们抛出那个最小的并推动新元素。
(我有一个C++
实现,但问题仍然与语言无关。)
答案 0 :(得分:13)
您想要的特定数据结构可能是隐式堆。原始数据结构只是一个数组;为方便起见,假设它的大小为N = 2 ^ n个元素,并且你想保持最大的N-1个元素。
我们的想法是将数组(称为A)视为深度为n的完整二叉树:
要将树维护为“堆”,您需要确保每个节点小于(或等于)其子节点。这称为“堆条件”:
使用堆来维护最大的N个元素:
基本上,这将导致任何替换元素“过滤”树,直到它达到其自然位置。这将最多花费n = log2(N)步骤,这是你能得到的最好的。此外,树的隐式形式允许非常快速的实现;现有的有界优先级队列库很可能使用隐式堆。
答案 1 :(得分:5)
在Java中,您可以使用已实现的SortedSet,例如通过TreeSet。每次插入后检查集合是否太大,如果是,则删除最后一个元素。
这是相当有效的,我已经成功地用它来解决几个Project Euler问题。
答案 2 :(得分:4)
priority_queue是C ++中最接近STL的东西。您可以将它包装在另一个类中,以创建自己的实现,自动修剪大小。
语言 - 非法(尽管可能不是内存碎片 - 安全):
std :: priority_queue为你做了第2步。
答案 3 :(得分:2)
有界优先级队列,我认为...... Java在其标准库中有类似的东西。 编辑:它被称为LinkedBlockingQueue
。我不确定C ++ STL是否包含类似的内容。
答案 4 :(得分:1)
是不是可以从排序的集合中获取前n个元素?
答案 5 :(得分:0)
是的,你可以保持最小的头部大小N. 然后在每次插入时将新项目与根项目进行比较 弹出根并插入项目,如果它比根“更大” 最后你最终获得了N个最大的项目
答案 6 :(得分:0)
在Pyhton中,使用heapq。在其周围创建一个小的包装,如下所示:
class TopN_Queue:
def __init__(self, n):
self.max_sz = n
self.data = []
def add(self, x):
if len(self.data) == self.max_sz:
heapq.heappushpop(self.data, x)
else:
heapq.heappush(self.data, x)
...
答案 7 :(得分:-1)
创建一个小堆,也存储一个计数器。
每当到达柜台时;提取分钟。
你可以这样做:O(1)insert,get-min和O(log log n)extract-min。[1]
或者你可以用O(log n)插入和O(1)做到这一点)对于其他提到的操作。[2]
[1]
M. Thorup,“整数优先级队列在恒定时间内减少关键并且单源最短路径问题”,在纽约州纽约市第35届年度ACM计算理论研讨会论文集中,USA,2003,pp.149-158。
[2]
G. S. Brodal,G。Lagogiannis,C。Makris,A。Tsakalidis和K. Tsichlas,“指针机器中的最佳手指搜索树”,J.Comput。 SYST。 Sci。,vol。 67,不。 2,pp.381-418,2003年9月。