部分排序(参见the Wikipedia page)比实际排序更有效。这些算法类似于排序算法。我将概述基于堆的部分排序(尽管在该页上它不是最有效的)。在
你想要最老的。您将一个接一个地将元素粘贴到堆中,当堆中的最新的元素太大时,将其弹出。由于堆很小,所以不必为插入和删除元素付出太多的代价。在
在标准情况下,您需要最小/最大的k元素。您需要满足total条件的最旧元素,因此通过保留total_size变量来跟踪total条件。在
代码:import heapq
def partial_bounded_sort(lst, n):
"""
Returns minimal collection of oldest elements
s.t. total size >= n.
"""
# `pqueue` holds (-atime, fsize) pairs.
# We negate atime, because heapq implements a min-heap,
# and we want to throw out newer things.
pqueue = []
total_size = 0
for atime, fsize in lst:
# Add it to the queue.
heapq.heappush(pqueue, (-atime, fsize))
total_size += fsize
# Pop off newest items which aren't needed for maintaining size.
topsize = pqueue[0][1]
while total_size - topsize >= n:
heapq.heappop(pqueue)
total_size -= topsize
topsize = pqueue[0][1]
# Un-negate atime and do a final sort.
oldest = sorted((-priority, fsize) for priority, fsize in pqueue)
return oldest
你可以做一些事情来微优化这段代码。例如,您可以用前几个条目填充列表,然后一次修复所有条目。在
复杂程度可能比排序好。在您的特定问题中,您不知道将返回的元素数量,甚至不知道一次队列中可以有多少元素。在最坏的情况下,你几乎对所有的列表进行排序。通过对列表进行预处理,看看是更容易找到一组新的事物还是一组旧的事物,就可以防止这种情况的发生。在
如果你想跟踪哪些项目是被删除的还是没有被删除的,你可以在原始列表中保留两个“指针”:一个用于跟踪已处理的内容,另一个标记“空闲”空间。当处理一个项目时,从列表中删除它,当从堆中丢弃一个项目时,将它放回列表中。列表将以不在堆中的项结尾,最后加上一些None项。在