Частичная сортировка (см. на странице Википедии ) более эффективна, чем фактическая сортировка.Алгоритмы аналогичны алгоритмам сортировки.Я обрисую частичную сортировку на основе кучи (хотя она не самая эффективная на этой странице).
Вы хотите самые старые.Вы вставляете элементы в кучу, один за другим, и выталкиваете новейший элемент в куче, когда он становится слишком большим.Поскольку куча остается маленькой, вы не платите столько, чтобы вставить и удалить элементы.
В стандартном случае вам нужны самые маленькие / самые большие k
элементы.Вам нужны самые старые элементы, удовлетворяющие общему условию, поэтому следите за общим состоянием, сохраняя переменную total_size
.
Код:
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
записей в конце.