blob: f8269e15e407e329096074687ac002903840fdc6 [file] [log] [blame]
Benjamin Petersonb6e112b2009-01-18 22:47:04 +00001# -*- coding: latin-1 -*-
Raymond Hettingerc46cb2a2004-04-19 19:06:21 +00002
3"""Heap queue algorithm (a.k.a. priority queue).
4
5Heaps are arrays for which a[k] <= a[2*k+1] and a[k] <= a[2*k+2] for
6all k, counting elements from 0. For the sake of comparison,
7non-existing elements are considered to be infinite. The interesting
8property of a heap is that a[0] is always its smallest element.
9
10Usage:
11
12heap = [] # creates an empty heap
13heappush(heap, item) # pushes a new item on the heap
14item = heappop(heap) # pops the smallest item from the heap
15item = heap[0] # smallest item on the heap without popping it
16heapify(x) # transforms list into a heap, in-place, in linear time
17item = heapreplace(heap, item) # pops and returns smallest item, and adds
18 # new item; the heap size is unchanged
19
20Our API differs from textbook heap algorithms as follows:
21
22- We use 0-based indexing. This makes the relationship between the
23 index for a node and the indexes for its children slightly less
24 obvious, but is more suitable since Python uses 0-based indexing.
25
26- Our heappop() method returns the smallest item, not the largest.
27
28These two make it possible to view the heap as a regular Python list
29without surprises: heap[0] is the smallest item, and heap.sort()
30maintains the heap invariant!
31"""
32
Raymond Hettinger33ecffb2004-06-10 05:03:17 +000033# Original code by Kevin O'Connor, augmented by Tim Peters and Raymond Hettinger
Raymond Hettingerc46cb2a2004-04-19 19:06:21 +000034
35__about__ = """Heap queues
36
37[explanation by François Pinard]
38
39Heaps are arrays for which a[k] <= a[2*k+1] and a[k] <= a[2*k+2] for
40all k, counting elements from 0. For the sake of comparison,
41non-existing elements are considered to be infinite. The interesting
42property of a heap is that a[0] is always its smallest element.
43
44The strange invariant above is meant to be an efficient memory
45representation for a tournament. The numbers below are `k', not a[k]:
46
47 0
48
49 1 2
50
51 3 4 5 6
52
53 7 8 9 10 11 12 13 14
54
55 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
56
57
58In the tree above, each cell `k' is topping `2*k+1' and `2*k+2'. In
Martin Panter6a8163a2016-04-15 02:14:19 +000059a usual binary tournament we see in sports, each cell is the winner
Raymond Hettingerc46cb2a2004-04-19 19:06:21 +000060over the two cells it tops, and we can trace the winner down the tree
61to see all opponents s/he had. However, in many computer applications
62of such tournaments, we do not need to trace the history of a winner.
63To be more memory efficient, when a winner is promoted, we try to
64replace it by something else at a lower level, and the rule becomes
65that a cell and the two cells it tops contain three different items,
66but the top cell "wins" over the two topped cells.
67
68If this heap invariant is protected at all time, index 0 is clearly
69the overall winner. The simplest algorithmic way to remove it and
70find the "next" winner is to move some loser (let's say cell 30 in the
71diagram above) into the 0 position, and then percolate this new 0 down
72the tree, exchanging values, until the invariant is re-established.
73This is clearly logarithmic on the total number of items in the tree.
74By iterating over all items, you get an O(n ln n) sort.
75
76A nice feature of this sort is that you can efficiently insert new
77items while the sort is going on, provided that the inserted items are
78not "better" than the last 0'th element you extracted. This is
79especially useful in simulation contexts, where the tree holds all
80incoming events, and the "win" condition means the smallest scheduled
81time. When an event schedule other events for execution, they are
82scheduled into the future, so they can easily go into the heap. So, a
83heap is a good structure for implementing schedulers (this is what I
84used for my MIDI sequencer :-).
85
86Various structures for implementing schedulers have been extensively
87studied, and heaps are good for this, as they are reasonably speedy,
88the speed is almost constant, and the worst case is not much different
89than the average case. However, there are other representations which
90are more efficient overall, yet the worst cases might be terrible.
91
92Heaps are also very useful in big disk sorts. You most probably all
93know that a big sort implies producing "runs" (which are pre-sorted
94sequences, which size is usually related to the amount of CPU memory),
95followed by a merging passes for these runs, which merging is often
96very cleverly organised[1]. It is very important that the initial
97sort produces the longest runs possible. Tournaments are a good way
98to that. If, using all the memory available to hold a tournament, you
99replace and percolate items that happen to fit the current run, you'll
100produce runs which are twice the size of the memory for random input,
101and much better for input fuzzily ordered.
102
103Moreover, if you output the 0'th item on disk and get an input which
104may not fit in the current tournament (because the value "wins" over
105the last output value), it cannot fit in the heap, so the size of the
106heap decreases. The freed memory could be cleverly reused immediately
107for progressively building a second heap, which grows at exactly the
108same rate the first heap is melting. When the first heap completely
109vanishes, you switch heaps and start a new run. Clever and quite
110effective!
111
112In a word, heaps are useful memory structures to know. I use them in
113a few applications, and I think it is good to keep a `heap' module
114around. :-)
115
116--------------------
117[1] The disk balancing algorithms which are current, nowadays, are
118more annoying than clever, and this is a consequence of the seeking
119capabilities of the disks. On devices which cannot seek, like big
120tape drives, the story was quite different, and one had to be very
121clever to ensure (far in advance) that each tape movement will be the
122most effective possible (that is, will best participate at
123"progressing" the merge). Some tapes were even able to read
124backwards, and this was also used to avoid the rewinding time.
125Believe me, real good tape sorts were quite spectacular to watch!
126From all times, sorting has always been a Great Art! :-)
127"""
128
Raymond Hettinger00166c52007-02-19 04:08:43 +0000129__all__ = ['heappush', 'heappop', 'heapify', 'heapreplace', 'merge',
Raymond Hettinger53bdf092008-03-13 19:03:51 +0000130 'nlargest', 'nsmallest', 'heappushpop']
Raymond Hettinger33ecffb2004-06-10 05:03:17 +0000131
Raymond Hettinger3e6aafe2013-03-05 02:15:01 -0500132from itertools import islice, count, imap, izip, tee, chain
Raymond Hettingerbe9b7652009-02-21 08:58:42 +0000133from operator import itemgetter
Raymond Hettingerc46cb2a2004-04-19 19:06:21 +0000134
Raymond Hettinger9b342c62011-04-13 11:15:58 -0700135def cmp_lt(x, y):
136 # Use __lt__ if available; otherwise, try __le__.
137 # In Py3.x, only __lt__ will be called.
138 return (x < y) if hasattr(x, '__lt__') else (not y <= x)
139
Raymond Hettingerc46cb2a2004-04-19 19:06:21 +0000140def heappush(heap, item):
141 """Push item onto heap, maintaining the heap invariant."""
142 heap.append(item)
143 _siftdown(heap, 0, len(heap)-1)
144
145def heappop(heap):
146 """Pop the smallest item off the heap, maintaining the heap invariant."""
147 lastelt = heap.pop() # raises appropriate IndexError if heap is empty
148 if heap:
149 returnitem = heap[0]
150 heap[0] = lastelt
151 _siftup(heap, 0)
152 else:
153 returnitem = lastelt
154 return returnitem
155
156def heapreplace(heap, item):
157 """Pop and return the current smallest value, and add the new item.
158
159 This is more efficient than heappop() followed by heappush(), and can be
160 more appropriate when using a fixed-size heap. Note that the value
161 returned may be larger than item! That constrains reasonable uses of
Raymond Hettinger8158e842004-09-06 07:04:09 +0000162 this routine unless written as part of a conditional replacement:
Raymond Hettinger28224f82004-06-20 09:07:53 +0000163
Raymond Hettinger8158e842004-09-06 07:04:09 +0000164 if item > heap[0]:
165 item = heapreplace(heap, item)
Raymond Hettingerc46cb2a2004-04-19 19:06:21 +0000166 """
167 returnitem = heap[0] # raises appropriate IndexError if heap is empty
168 heap[0] = item
169 _siftup(heap, 0)
170 return returnitem
171
Raymond Hettinger53bdf092008-03-13 19:03:51 +0000172def heappushpop(heap, item):
173 """Fast version of a heappush followed by a heappop."""
Raymond Hettinger9b342c62011-04-13 11:15:58 -0700174 if heap and cmp_lt(heap[0], item):
Raymond Hettinger53bdf092008-03-13 19:03:51 +0000175 item, heap[0] = heap[0], item
176 _siftup(heap, 0)
177 return item
178
Raymond Hettingerc46cb2a2004-04-19 19:06:21 +0000179def heapify(x):
Éric Araujo4800d642011-04-15 23:34:31 +0200180 """Transform list into a heap, in-place, in O(len(x)) time."""
Raymond Hettingerc46cb2a2004-04-19 19:06:21 +0000181 n = len(x)
182 # Transform bottom-up. The largest index there's any point to looking at
183 # is the largest with a child index in-range, so must have 2*i + 1 < n,
184 # or i < (n-1)/2. If n is even = 2*j, this is (2*j-1)/2 = j-1/2 so
185 # j-1 is the largest, which is n//2 - 1. If n is odd = 2*j+1, this is
186 # (2*j+1-1)/2 = j so j-1 is the largest, and that's again n//2-1.
187 for i in reversed(xrange(n//2)):
188 _siftup(x, i)
189
Raymond Hettinger3e6aafe2013-03-05 02:15:01 -0500190def _heappushpop_max(heap, item):
191 """Maxheap version of a heappush followed by a heappop."""
192 if heap and cmp_lt(item, heap[0]):
193 item, heap[0] = heap[0], item
194 _siftup_max(heap, 0)
195 return item
196
197def _heapify_max(x):
198 """Transform list into a maxheap, in-place, in O(len(x)) time."""
199 n = len(x)
200 for i in reversed(range(n//2)):
201 _siftup_max(x, i)
202
Raymond Hettingere1defa42004-11-29 05:54:48 +0000203def nlargest(n, iterable):
Raymond Hettinger33ecffb2004-06-10 05:03:17 +0000204 """Find the n largest elements in a dataset.
205
206 Equivalent to: sorted(iterable, reverse=True)[:n]
207 """
Raymond Hettingere11a47e2011-10-30 14:29:06 -0700208 if n < 0:
209 return []
Raymond Hettinger33ecffb2004-06-10 05:03:17 +0000210 it = iter(iterable)
211 result = list(islice(it, n))
212 if not result:
213 return result
214 heapify(result)
Raymond Hettinger83aa6a32008-03-13 19:33:34 +0000215 _heappushpop = heappushpop
Raymond Hettinger33ecffb2004-06-10 05:03:17 +0000216 for elem in it:
Benjamin Petersonfb921e22009-01-31 21:00:10 +0000217 _heappushpop(result, elem)
Raymond Hettinger33ecffb2004-06-10 05:03:17 +0000218 result.sort(reverse=True)
219 return result
220
Raymond Hettingere1defa42004-11-29 05:54:48 +0000221def nsmallest(n, iterable):
Raymond Hettinger33ecffb2004-06-10 05:03:17 +0000222 """Find the n smallest elements in a dataset.
223
224 Equivalent to: sorted(iterable)[:n]
225 """
Raymond Hettingere11a47e2011-10-30 14:29:06 -0700226 if n < 0:
227 return []
Raymond Hettinger3e6aafe2013-03-05 02:15:01 -0500228 it = iter(iterable)
229 result = list(islice(it, n))
230 if not result:
Raymond Hettingerb25aa362004-06-12 08:33:36 +0000231 return result
Raymond Hettinger3e6aafe2013-03-05 02:15:01 -0500232 _heapify_max(result)
233 _heappushpop = _heappushpop_max
234 for elem in it:
235 _heappushpop(result, elem)
236 result.sort()
237 return result
Raymond Hettinger33ecffb2004-06-10 05:03:17 +0000238
Raymond Hettingerc46cb2a2004-04-19 19:06:21 +0000239# 'heap' is a heap at all indices >= startpos, except possibly for pos. pos
240# is the index of a leaf with a possibly out-of-order value. Restore the
241# heap invariant.
242def _siftdown(heap, startpos, pos):
243 newitem = heap[pos]
244 # Follow the path to the root, moving parents down until finding a place
245 # newitem fits.
246 while pos > startpos:
247 parentpos = (pos - 1) >> 1
248 parent = heap[parentpos]
Raymond Hettinger9b342c62011-04-13 11:15:58 -0700249 if cmp_lt(newitem, parent):
Raymond Hettinger6d7702e2008-05-31 03:24:31 +0000250 heap[pos] = parent
251 pos = parentpos
252 continue
253 break
Raymond Hettingerc46cb2a2004-04-19 19:06:21 +0000254 heap[pos] = newitem
255
256# The child indices of heap index pos are already heaps, and we want to make
257# a heap at index pos too. We do this by bubbling the smaller child of
258# pos up (and so on with that child's children, etc) until hitting a leaf,
259# then using _siftdown to move the oddball originally at index pos into place.
260#
261# We *could* break out of the loop as soon as we find a pos where newitem <=
262# both its children, but turns out that's not a good idea, and despite that
263# many books write the algorithm that way. During a heap pop, the last array
264# element is sifted in, and that tends to be large, so that comparing it
265# against values starting from the root usually doesn't pay (= usually doesn't
266# get us out of the loop early). See Knuth, Volume 3, where this is
267# explained and quantified in an exercise.
268#
269# Cutting the # of comparisons is important, since these routines have no
270# way to extract "the priority" from an array element, so that intelligence
271# is likely to be hiding in custom __cmp__ methods, or in array elements
272# storing (priority, record) tuples. Comparisons are thus potentially
273# expensive.
274#
275# On random arrays of length 1000, making this change cut the number of
276# comparisons made by heapify() a little, and those made by exhaustive
277# heappop() a lot, in accord with theory. Here are typical results from 3
278# runs (3 just to demonstrate how small the variance is):
279#
280# Compares needed by heapify Compares needed by 1000 heappops
281# -------------------------- --------------------------------
282# 1837 cut to 1663 14996 cut to 8680
283# 1855 cut to 1659 14966 cut to 8678
284# 1847 cut to 1660 15024 cut to 8703
285#
286# Building the heap by using heappush() 1000 times instead required
287# 2198, 2148, and 2219 compares: heapify() is more efficient, when
288# you can use it.
289#
290# The total compares needed by list.sort() on the same lists were 8627,
291# 8627, and 8632 (this should be compared to the sum of heapify() and
292# heappop() compares): list.sort() is (unsurprisingly!) more efficient
293# for sorting.
294
295def _siftup(heap, pos):
296 endpos = len(heap)
297 startpos = pos
298 newitem = heap[pos]
299 # Bubble up the smaller child until hitting a leaf.
300 childpos = 2*pos + 1 # leftmost child position
301 while childpos < endpos:
302 # Set childpos to index of smaller child.
303 rightpos = childpos + 1
Raymond Hettinger9b342c62011-04-13 11:15:58 -0700304 if rightpos < endpos and not cmp_lt(heap[childpos], heap[rightpos]):
Raymond Hettingerc46cb2a2004-04-19 19:06:21 +0000305 childpos = rightpos
306 # Move the smaller child up.
307 heap[pos] = heap[childpos]
308 pos = childpos
309 childpos = 2*pos + 1
310 # The leaf at pos is empty now. Put newitem there, and bubble it up
311 # to its final resting place (by sifting its parents down).
312 heap[pos] = newitem
313 _siftdown(heap, startpos, pos)
314
Raymond Hettinger3e6aafe2013-03-05 02:15:01 -0500315def _siftdown_max(heap, startpos, pos):
316 'Maxheap variant of _siftdown'
317 newitem = heap[pos]
318 # Follow the path to the root, moving parents down until finding a place
319 # newitem fits.
320 while pos > startpos:
321 parentpos = (pos - 1) >> 1
322 parent = heap[parentpos]
323 if cmp_lt(parent, newitem):
324 heap[pos] = parent
325 pos = parentpos
326 continue
327 break
328 heap[pos] = newitem
329
330def _siftup_max(heap, pos):
331 'Maxheap variant of _siftup'
332 endpos = len(heap)
333 startpos = pos
334 newitem = heap[pos]
335 # Bubble up the larger child until hitting a leaf.
336 childpos = 2*pos + 1 # leftmost child position
337 while childpos < endpos:
338 # Set childpos to index of larger child.
339 rightpos = childpos + 1
340 if rightpos < endpos and not cmp_lt(heap[rightpos], heap[childpos]):
341 childpos = rightpos
342 # Move the larger child up.
343 heap[pos] = heap[childpos]
344 pos = childpos
345 childpos = 2*pos + 1
346 # The leaf at pos is empty now. Put newitem there, and bubble it up
347 # to its final resting place (by sifting its parents down).
348 heap[pos] = newitem
349 _siftdown_max(heap, startpos, pos)
350
Raymond Hettingerc46cb2a2004-04-19 19:06:21 +0000351# If available, use C implementation
352try:
Raymond Hettingerb006fcc2009-03-29 18:51:11 +0000353 from _heapq import *
Raymond Hettingerc46cb2a2004-04-19 19:06:21 +0000354except ImportError:
355 pass
356
Raymond Hettinger00166c52007-02-19 04:08:43 +0000357def merge(*iterables):
358 '''Merge multiple sorted inputs into a single sorted output.
359
Raymond Hettinger3035d232007-02-28 18:27:41 +0000360 Similar to sorted(itertools.chain(*iterables)) but returns a generator,
Raymond Hettingercbac8ce2007-02-19 18:15:04 +0000361 does not pull the data into memory all at once, and assumes that each of
362 the input streams is already sorted (smallest to largest).
Raymond Hettinger00166c52007-02-19 04:08:43 +0000363
364 >>> list(merge([1,3,5,7], [0,2,4,8], [5,10,15,20], [], [25]))
365 [0, 1, 2, 3, 4, 5, 5, 7, 8, 10, 15, 20, 25]
366
367 '''
Raymond Hettinger45eb0f12007-02-19 06:59:32 +0000368 _heappop, _heapreplace, _StopIteration = heappop, heapreplace, StopIteration
Raymond Hettinger39659f22013-09-14 22:17:39 -0700369 _len = len
Raymond Hettinger00166c52007-02-19 04:08:43 +0000370
371 h = []
372 h_append = h.append
Raymond Hettinger54da9812007-02-19 05:28:28 +0000373 for itnum, it in enumerate(map(iter, iterables)):
Raymond Hettinger00166c52007-02-19 04:08:43 +0000374 try:
375 next = it.next
Raymond Hettinger54da9812007-02-19 05:28:28 +0000376 h_append([next(), itnum, next])
Raymond Hettinger00166c52007-02-19 04:08:43 +0000377 except _StopIteration:
378 pass
379 heapify(h)
380
Raymond Hettinger39659f22013-09-14 22:17:39 -0700381 while _len(h) > 1:
Raymond Hettinger00166c52007-02-19 04:08:43 +0000382 try:
Raymond Hettinger9a2325f2013-10-28 02:39:04 -0600383 while 1:
Raymond Hettinger39659f22013-09-14 22:17:39 -0700384 v, itnum, next = s = h[0]
Raymond Hettinger00166c52007-02-19 04:08:43 +0000385 yield v
Raymond Hettinger54da9812007-02-19 05:28:28 +0000386 s[0] = next() # raises StopIteration when exhausted
Raymond Hettinger45eb0f12007-02-19 06:59:32 +0000387 _heapreplace(h, s) # restore heap condition
Raymond Hettinger00166c52007-02-19 04:08:43 +0000388 except _StopIteration:
Raymond Hettinger54da9812007-02-19 05:28:28 +0000389 _heappop(h) # remove empty iterator
Raymond Hettinger39659f22013-09-14 22:17:39 -0700390 if h:
391 # fast case when only a single iterator remains
392 v, itnum, next = h[0]
393 yield v
394 for v in next.__self__:
395 yield v
Raymond Hettinger00166c52007-02-19 04:08:43 +0000396
Raymond Hettinger4901a1f2004-12-02 08:59:14 +0000397# Extend the implementations of nsmallest and nlargest to use a key= argument
398_nsmallest = nsmallest
399def nsmallest(n, iterable, key=None):
400 """Find the n smallest elements in a dataset.
401
402 Equivalent to: sorted(iterable, key=key)[:n]
403 """
Raymond Hettingerb5bc33c2009-01-12 10:37:32 +0000404 # Short-cut for n==1 is to use min() when len(iterable)>0
405 if n == 1:
406 it = iter(iterable)
407 head = list(islice(it, 1))
408 if not head:
409 return []
410 if key is None:
411 return [min(chain(head, it))]
412 return [min(chain(head, it), key=key)]
413
Éric Araujo4800d642011-04-15 23:34:31 +0200414 # When n>=size, it's faster to use sorted()
Raymond Hettingerb5bc33c2009-01-12 10:37:32 +0000415 try:
416 size = len(iterable)
417 except (TypeError, AttributeError):
418 pass
419 else:
420 if n >= size:
421 return sorted(iterable, key=key)[:n]
422
423 # When key is none, use simpler decoration
Georg Brandlfe427892009-01-03 22:03:11 +0000424 if key is None:
425 it = izip(iterable, count()) # decorate
426 result = _nsmallest(n, it)
427 return map(itemgetter(0), result) # undecorate
Raymond Hettingerb5bc33c2009-01-12 10:37:32 +0000428
429 # General case, slowest method
Raymond Hettinger4901a1f2004-12-02 08:59:14 +0000430 in1, in2 = tee(iterable)
431 it = izip(imap(key, in1), count(), in2) # decorate
432 result = _nsmallest(n, it)
433 return map(itemgetter(2), result) # undecorate
434
435_nlargest = nlargest
436def nlargest(n, iterable, key=None):
437 """Find the n largest elements in a dataset.
438
439 Equivalent to: sorted(iterable, key=key, reverse=True)[:n]
440 """
Raymond Hettingerb5bc33c2009-01-12 10:37:32 +0000441
442 # Short-cut for n==1 is to use max() when len(iterable)>0
443 if n == 1:
444 it = iter(iterable)
445 head = list(islice(it, 1))
446 if not head:
447 return []
448 if key is None:
449 return [max(chain(head, it))]
450 return [max(chain(head, it), key=key)]
451
Éric Araujo4800d642011-04-15 23:34:31 +0200452 # When n>=size, it's faster to use sorted()
Raymond Hettingerb5bc33c2009-01-12 10:37:32 +0000453 try:
454 size = len(iterable)
455 except (TypeError, AttributeError):
456 pass
457 else:
458 if n >= size:
459 return sorted(iterable, key=key, reverse=True)[:n]
460
461 # When key is none, use simpler decoration
Georg Brandlfe427892009-01-03 22:03:11 +0000462 if key is None:
Raymond Hettingerbe9b7652009-02-21 08:58:42 +0000463 it = izip(iterable, count(0,-1)) # decorate
Georg Brandlfe427892009-01-03 22:03:11 +0000464 result = _nlargest(n, it)
465 return map(itemgetter(0), result) # undecorate
Raymond Hettingerb5bc33c2009-01-12 10:37:32 +0000466
467 # General case, slowest method
Raymond Hettinger4901a1f2004-12-02 08:59:14 +0000468 in1, in2 = tee(iterable)
Raymond Hettingerbe9b7652009-02-21 08:58:42 +0000469 it = izip(imap(key, in1), count(0,-1), in2) # decorate
Raymond Hettinger4901a1f2004-12-02 08:59:14 +0000470 result = _nlargest(n, it)
471 return map(itemgetter(2), result) # undecorate
472
Raymond Hettingerc46cb2a2004-04-19 19:06:21 +0000473if __name__ == "__main__":
474 # Simple sanity test
475 heap = []
476 data = [1, 3, 5, 7, 9, 2, 4, 6, 8, 0]
477 for item in data:
478 heappush(heap, item)
479 sort = []
480 while heap:
481 sort.append(heappop(heap))
482 print sort
Raymond Hettinger00166c52007-02-19 04:08:43 +0000483
484 import doctest
485 doctest.testmod()