1*cda5da8dSAndroid Build Coastguard Worker"""Heap queue algorithm (a.k.a. priority queue). 2*cda5da8dSAndroid Build Coastguard Worker 3*cda5da8dSAndroid Build Coastguard WorkerHeaps are arrays for which a[k] <= a[2*k+1] and a[k] <= a[2*k+2] for 4*cda5da8dSAndroid Build Coastguard Workerall k, counting elements from 0. For the sake of comparison, 5*cda5da8dSAndroid Build Coastguard Workernon-existing elements are considered to be infinite. The interesting 6*cda5da8dSAndroid Build Coastguard Workerproperty of a heap is that a[0] is always its smallest element. 7*cda5da8dSAndroid Build Coastguard Worker 8*cda5da8dSAndroid Build Coastguard WorkerUsage: 9*cda5da8dSAndroid Build Coastguard Worker 10*cda5da8dSAndroid Build Coastguard Workerheap = [] # creates an empty heap 11*cda5da8dSAndroid Build Coastguard Workerheappush(heap, item) # pushes a new item on the heap 12*cda5da8dSAndroid Build Coastguard Workeritem = heappop(heap) # pops the smallest item from the heap 13*cda5da8dSAndroid Build Coastguard Workeritem = heap[0] # smallest item on the heap without popping it 14*cda5da8dSAndroid Build Coastguard Workerheapify(x) # transforms list into a heap, in-place, in linear time 15*cda5da8dSAndroid Build Coastguard Workeritem = heappushpop(heap, item) # pushes a new item and then returns 16*cda5da8dSAndroid Build Coastguard Worker # the smallest item; the heap size is unchanged 17*cda5da8dSAndroid Build Coastguard Workeritem = heapreplace(heap, item) # pops and returns smallest item, and adds 18*cda5da8dSAndroid Build Coastguard Worker # new item; the heap size is unchanged 19*cda5da8dSAndroid Build Coastguard Worker 20*cda5da8dSAndroid Build Coastguard WorkerOur API differs from textbook heap algorithms as follows: 21*cda5da8dSAndroid Build Coastguard Worker 22*cda5da8dSAndroid Build Coastguard Worker- We use 0-based indexing. This makes the relationship between the 23*cda5da8dSAndroid Build Coastguard Worker index for a node and the indexes for its children slightly less 24*cda5da8dSAndroid Build Coastguard Worker obvious, but is more suitable since Python uses 0-based indexing. 25*cda5da8dSAndroid Build Coastguard Worker 26*cda5da8dSAndroid Build Coastguard Worker- Our heappop() method returns the smallest item, not the largest. 27*cda5da8dSAndroid Build Coastguard Worker 28*cda5da8dSAndroid Build Coastguard WorkerThese two make it possible to view the heap as a regular Python list 29*cda5da8dSAndroid Build Coastguard Workerwithout surprises: heap[0] is the smallest item, and heap.sort() 30*cda5da8dSAndroid Build Coastguard Workermaintains the heap invariant! 31*cda5da8dSAndroid Build Coastguard Worker""" 32*cda5da8dSAndroid Build Coastguard Worker 33*cda5da8dSAndroid Build Coastguard Worker# Original code by Kevin O'Connor, augmented by Tim Peters and Raymond Hettinger 34*cda5da8dSAndroid Build Coastguard Worker 35*cda5da8dSAndroid Build Coastguard Worker__about__ = """Heap queues 36*cda5da8dSAndroid Build Coastguard Worker 37*cda5da8dSAndroid Build Coastguard Worker[explanation by François Pinard] 38*cda5da8dSAndroid Build Coastguard Worker 39*cda5da8dSAndroid Build Coastguard WorkerHeaps are arrays for which a[k] <= a[2*k+1] and a[k] <= a[2*k+2] for 40*cda5da8dSAndroid Build Coastguard Workerall k, counting elements from 0. For the sake of comparison, 41*cda5da8dSAndroid Build Coastguard Workernon-existing elements are considered to be infinite. The interesting 42*cda5da8dSAndroid Build Coastguard Workerproperty of a heap is that a[0] is always its smallest element. 43*cda5da8dSAndroid Build Coastguard Worker 44*cda5da8dSAndroid Build Coastguard WorkerThe strange invariant above is meant to be an efficient memory 45*cda5da8dSAndroid Build Coastguard Workerrepresentation for a tournament. The numbers below are `k', not a[k]: 46*cda5da8dSAndroid Build Coastguard Worker 47*cda5da8dSAndroid Build Coastguard Worker 0 48*cda5da8dSAndroid Build Coastguard Worker 49*cda5da8dSAndroid Build Coastguard Worker 1 2 50*cda5da8dSAndroid Build Coastguard Worker 51*cda5da8dSAndroid Build Coastguard Worker 3 4 5 6 52*cda5da8dSAndroid Build Coastguard Worker 53*cda5da8dSAndroid Build Coastguard Worker 7 8 9 10 11 12 13 14 54*cda5da8dSAndroid Build Coastguard Worker 55*cda5da8dSAndroid Build Coastguard Worker 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 56*cda5da8dSAndroid Build Coastguard Worker 57*cda5da8dSAndroid Build Coastguard Worker 58*cda5da8dSAndroid Build Coastguard WorkerIn the tree above, each cell `k' is topping `2*k+1' and `2*k+2'. In 59*cda5da8dSAndroid Build Coastguard Workera usual binary tournament we see in sports, each cell is the winner 60*cda5da8dSAndroid Build Coastguard Workerover the two cells it tops, and we can trace the winner down the tree 61*cda5da8dSAndroid Build Coastguard Workerto see all opponents s/he had. However, in many computer applications 62*cda5da8dSAndroid Build Coastguard Workerof such tournaments, we do not need to trace the history of a winner. 63*cda5da8dSAndroid Build Coastguard WorkerTo be more memory efficient, when a winner is promoted, we try to 64*cda5da8dSAndroid Build Coastguard Workerreplace it by something else at a lower level, and the rule becomes 65*cda5da8dSAndroid Build Coastguard Workerthat a cell and the two cells it tops contain three different items, 66*cda5da8dSAndroid Build Coastguard Workerbut the top cell "wins" over the two topped cells. 67*cda5da8dSAndroid Build Coastguard Worker 68*cda5da8dSAndroid Build Coastguard WorkerIf this heap invariant is protected at all time, index 0 is clearly 69*cda5da8dSAndroid Build Coastguard Workerthe overall winner. The simplest algorithmic way to remove it and 70*cda5da8dSAndroid Build Coastguard Workerfind the "next" winner is to move some loser (let's say cell 30 in the 71*cda5da8dSAndroid Build Coastguard Workerdiagram above) into the 0 position, and then percolate this new 0 down 72*cda5da8dSAndroid Build Coastguard Workerthe tree, exchanging values, until the invariant is re-established. 73*cda5da8dSAndroid Build Coastguard WorkerThis is clearly logarithmic on the total number of items in the tree. 74*cda5da8dSAndroid Build Coastguard WorkerBy iterating over all items, you get an O(n ln n) sort. 75*cda5da8dSAndroid Build Coastguard Worker 76*cda5da8dSAndroid Build Coastguard WorkerA nice feature of this sort is that you can efficiently insert new 77*cda5da8dSAndroid Build Coastguard Workeritems while the sort is going on, provided that the inserted items are 78*cda5da8dSAndroid Build Coastguard Workernot "better" than the last 0'th element you extracted. This is 79*cda5da8dSAndroid Build Coastguard Workerespecially useful in simulation contexts, where the tree holds all 80*cda5da8dSAndroid Build Coastguard Workerincoming events, and the "win" condition means the smallest scheduled 81*cda5da8dSAndroid Build Coastguard Workertime. When an event schedule other events for execution, they are 82*cda5da8dSAndroid Build Coastguard Workerscheduled into the future, so they can easily go into the heap. So, a 83*cda5da8dSAndroid Build Coastguard Workerheap is a good structure for implementing schedulers (this is what I 84*cda5da8dSAndroid Build Coastguard Workerused for my MIDI sequencer :-). 85*cda5da8dSAndroid Build Coastguard Worker 86*cda5da8dSAndroid Build Coastguard WorkerVarious structures for implementing schedulers have been extensively 87*cda5da8dSAndroid Build Coastguard Workerstudied, and heaps are good for this, as they are reasonably speedy, 88*cda5da8dSAndroid Build Coastguard Workerthe speed is almost constant, and the worst case is not much different 89*cda5da8dSAndroid Build Coastguard Workerthan the average case. However, there are other representations which 90*cda5da8dSAndroid Build Coastguard Workerare more efficient overall, yet the worst cases might be terrible. 91*cda5da8dSAndroid Build Coastguard Worker 92*cda5da8dSAndroid Build Coastguard WorkerHeaps are also very useful in big disk sorts. You most probably all 93*cda5da8dSAndroid Build Coastguard Workerknow that a big sort implies producing "runs" (which are pre-sorted 94*cda5da8dSAndroid Build Coastguard Workersequences, which size is usually related to the amount of CPU memory), 95*cda5da8dSAndroid Build Coastguard Workerfollowed by a merging passes for these runs, which merging is often 96*cda5da8dSAndroid Build Coastguard Workervery cleverly organised[1]. It is very important that the initial 97*cda5da8dSAndroid Build Coastguard Workersort produces the longest runs possible. Tournaments are a good way 98*cda5da8dSAndroid Build Coastguard Workerto that. If, using all the memory available to hold a tournament, you 99*cda5da8dSAndroid Build Coastguard Workerreplace and percolate items that happen to fit the current run, you'll 100*cda5da8dSAndroid Build Coastguard Workerproduce runs which are twice the size of the memory for random input, 101*cda5da8dSAndroid Build Coastguard Workerand much better for input fuzzily ordered. 102*cda5da8dSAndroid Build Coastguard Worker 103*cda5da8dSAndroid Build Coastguard WorkerMoreover, if you output the 0'th item on disk and get an input which 104*cda5da8dSAndroid Build Coastguard Workermay not fit in the current tournament (because the value "wins" over 105*cda5da8dSAndroid Build Coastguard Workerthe last output value), it cannot fit in the heap, so the size of the 106*cda5da8dSAndroid Build Coastguard Workerheap decreases. The freed memory could be cleverly reused immediately 107*cda5da8dSAndroid Build Coastguard Workerfor progressively building a second heap, which grows at exactly the 108*cda5da8dSAndroid Build Coastguard Workersame rate the first heap is melting. When the first heap completely 109*cda5da8dSAndroid Build Coastguard Workervanishes, you switch heaps and start a new run. Clever and quite 110*cda5da8dSAndroid Build Coastguard Workereffective! 111*cda5da8dSAndroid Build Coastguard Worker 112*cda5da8dSAndroid Build Coastguard WorkerIn a word, heaps are useful memory structures to know. I use them in 113*cda5da8dSAndroid Build Coastguard Workera few applications, and I think it is good to keep a `heap' module 114*cda5da8dSAndroid Build Coastguard Workeraround. :-) 115*cda5da8dSAndroid Build Coastguard Worker 116*cda5da8dSAndroid Build Coastguard Worker-------------------- 117*cda5da8dSAndroid Build Coastguard Worker[1] The disk balancing algorithms which are current, nowadays, are 118*cda5da8dSAndroid Build Coastguard Workermore annoying than clever, and this is a consequence of the seeking 119*cda5da8dSAndroid Build Coastguard Workercapabilities of the disks. On devices which cannot seek, like big 120*cda5da8dSAndroid Build Coastguard Workertape drives, the story was quite different, and one had to be very 121*cda5da8dSAndroid Build Coastguard Workerclever to ensure (far in advance) that each tape movement will be the 122*cda5da8dSAndroid Build Coastguard Workermost effective possible (that is, will best participate at 123*cda5da8dSAndroid Build Coastguard Worker"progressing" the merge). Some tapes were even able to read 124*cda5da8dSAndroid Build Coastguard Workerbackwards, and this was also used to avoid the rewinding time. 125*cda5da8dSAndroid Build Coastguard WorkerBelieve me, real good tape sorts were quite spectacular to watch! 126*cda5da8dSAndroid Build Coastguard WorkerFrom all times, sorting has always been a Great Art! :-) 127*cda5da8dSAndroid Build Coastguard Worker""" 128*cda5da8dSAndroid Build Coastguard Worker 129*cda5da8dSAndroid Build Coastguard Worker__all__ = ['heappush', 'heappop', 'heapify', 'heapreplace', 'merge', 130*cda5da8dSAndroid Build Coastguard Worker 'nlargest', 'nsmallest', 'heappushpop'] 131*cda5da8dSAndroid Build Coastguard Worker 132*cda5da8dSAndroid Build Coastguard Workerdef heappush(heap, item): 133*cda5da8dSAndroid Build Coastguard Worker """Push item onto heap, maintaining the heap invariant.""" 134*cda5da8dSAndroid Build Coastguard Worker heap.append(item) 135*cda5da8dSAndroid Build Coastguard Worker _siftdown(heap, 0, len(heap)-1) 136*cda5da8dSAndroid Build Coastguard Worker 137*cda5da8dSAndroid Build Coastguard Workerdef heappop(heap): 138*cda5da8dSAndroid Build Coastguard Worker """Pop the smallest item off the heap, maintaining the heap invariant.""" 139*cda5da8dSAndroid Build Coastguard Worker lastelt = heap.pop() # raises appropriate IndexError if heap is empty 140*cda5da8dSAndroid Build Coastguard Worker if heap: 141*cda5da8dSAndroid Build Coastguard Worker returnitem = heap[0] 142*cda5da8dSAndroid Build Coastguard Worker heap[0] = lastelt 143*cda5da8dSAndroid Build Coastguard Worker _siftup(heap, 0) 144*cda5da8dSAndroid Build Coastguard Worker return returnitem 145*cda5da8dSAndroid Build Coastguard Worker return lastelt 146*cda5da8dSAndroid Build Coastguard Worker 147*cda5da8dSAndroid Build Coastguard Workerdef heapreplace(heap, item): 148*cda5da8dSAndroid Build Coastguard Worker """Pop and return the current smallest value, and add the new item. 149*cda5da8dSAndroid Build Coastguard Worker 150*cda5da8dSAndroid Build Coastguard Worker This is more efficient than heappop() followed by heappush(), and can be 151*cda5da8dSAndroid Build Coastguard Worker more appropriate when using a fixed-size heap. Note that the value 152*cda5da8dSAndroid Build Coastguard Worker returned may be larger than item! That constrains reasonable uses of 153*cda5da8dSAndroid Build Coastguard Worker this routine unless written as part of a conditional replacement: 154*cda5da8dSAndroid Build Coastguard Worker 155*cda5da8dSAndroid Build Coastguard Worker if item > heap[0]: 156*cda5da8dSAndroid Build Coastguard Worker item = heapreplace(heap, item) 157*cda5da8dSAndroid Build Coastguard Worker """ 158*cda5da8dSAndroid Build Coastguard Worker returnitem = heap[0] # raises appropriate IndexError if heap is empty 159*cda5da8dSAndroid Build Coastguard Worker heap[0] = item 160*cda5da8dSAndroid Build Coastguard Worker _siftup(heap, 0) 161*cda5da8dSAndroid Build Coastguard Worker return returnitem 162*cda5da8dSAndroid Build Coastguard Worker 163*cda5da8dSAndroid Build Coastguard Workerdef heappushpop(heap, item): 164*cda5da8dSAndroid Build Coastguard Worker """Fast version of a heappush followed by a heappop.""" 165*cda5da8dSAndroid Build Coastguard Worker if heap and heap[0] < item: 166*cda5da8dSAndroid Build Coastguard Worker item, heap[0] = heap[0], item 167*cda5da8dSAndroid Build Coastguard Worker _siftup(heap, 0) 168*cda5da8dSAndroid Build Coastguard Worker return item 169*cda5da8dSAndroid Build Coastguard Worker 170*cda5da8dSAndroid Build Coastguard Workerdef heapify(x): 171*cda5da8dSAndroid Build Coastguard Worker """Transform list into a heap, in-place, in O(len(x)) time.""" 172*cda5da8dSAndroid Build Coastguard Worker n = len(x) 173*cda5da8dSAndroid Build Coastguard Worker # Transform bottom-up. The largest index there's any point to looking at 174*cda5da8dSAndroid Build Coastguard Worker # is the largest with a child index in-range, so must have 2*i + 1 < n, 175*cda5da8dSAndroid Build Coastguard Worker # or i < (n-1)/2. If n is even = 2*j, this is (2*j-1)/2 = j-1/2 so 176*cda5da8dSAndroid Build Coastguard Worker # j-1 is the largest, which is n//2 - 1. If n is odd = 2*j+1, this is 177*cda5da8dSAndroid Build Coastguard Worker # (2*j+1-1)/2 = j so j-1 is the largest, and that's again n//2-1. 178*cda5da8dSAndroid Build Coastguard Worker for i in reversed(range(n//2)): 179*cda5da8dSAndroid Build Coastguard Worker _siftup(x, i) 180*cda5da8dSAndroid Build Coastguard Worker 181*cda5da8dSAndroid Build Coastguard Workerdef _heappop_max(heap): 182*cda5da8dSAndroid Build Coastguard Worker """Maxheap version of a heappop.""" 183*cda5da8dSAndroid Build Coastguard Worker lastelt = heap.pop() # raises appropriate IndexError if heap is empty 184*cda5da8dSAndroid Build Coastguard Worker if heap: 185*cda5da8dSAndroid Build Coastguard Worker returnitem = heap[0] 186*cda5da8dSAndroid Build Coastguard Worker heap[0] = lastelt 187*cda5da8dSAndroid Build Coastguard Worker _siftup_max(heap, 0) 188*cda5da8dSAndroid Build Coastguard Worker return returnitem 189*cda5da8dSAndroid Build Coastguard Worker return lastelt 190*cda5da8dSAndroid Build Coastguard Worker 191*cda5da8dSAndroid Build Coastguard Workerdef _heapreplace_max(heap, item): 192*cda5da8dSAndroid Build Coastguard Worker """Maxheap version of a heappop followed by a heappush.""" 193*cda5da8dSAndroid Build Coastguard Worker returnitem = heap[0] # raises appropriate IndexError if heap is empty 194*cda5da8dSAndroid Build Coastguard Worker heap[0] = item 195*cda5da8dSAndroid Build Coastguard Worker _siftup_max(heap, 0) 196*cda5da8dSAndroid Build Coastguard Worker return returnitem 197*cda5da8dSAndroid Build Coastguard Worker 198*cda5da8dSAndroid Build Coastguard Workerdef _heapify_max(x): 199*cda5da8dSAndroid Build Coastguard Worker """Transform list into a maxheap, in-place, in O(len(x)) time.""" 200*cda5da8dSAndroid Build Coastguard Worker n = len(x) 201*cda5da8dSAndroid Build Coastguard Worker for i in reversed(range(n//2)): 202*cda5da8dSAndroid Build Coastguard Worker _siftup_max(x, i) 203*cda5da8dSAndroid Build Coastguard Worker 204*cda5da8dSAndroid Build Coastguard Worker# 'heap' is a heap at all indices >= startpos, except possibly for pos. pos 205*cda5da8dSAndroid Build Coastguard Worker# is the index of a leaf with a possibly out-of-order value. Restore the 206*cda5da8dSAndroid Build Coastguard Worker# heap invariant. 207*cda5da8dSAndroid Build Coastguard Workerdef _siftdown(heap, startpos, pos): 208*cda5da8dSAndroid Build Coastguard Worker newitem = heap[pos] 209*cda5da8dSAndroid Build Coastguard Worker # Follow the path to the root, moving parents down until finding a place 210*cda5da8dSAndroid Build Coastguard Worker # newitem fits. 211*cda5da8dSAndroid Build Coastguard Worker while pos > startpos: 212*cda5da8dSAndroid Build Coastguard Worker parentpos = (pos - 1) >> 1 213*cda5da8dSAndroid Build Coastguard Worker parent = heap[parentpos] 214*cda5da8dSAndroid Build Coastguard Worker if newitem < parent: 215*cda5da8dSAndroid Build Coastguard Worker heap[pos] = parent 216*cda5da8dSAndroid Build Coastguard Worker pos = parentpos 217*cda5da8dSAndroid Build Coastguard Worker continue 218*cda5da8dSAndroid Build Coastguard Worker break 219*cda5da8dSAndroid Build Coastguard Worker heap[pos] = newitem 220*cda5da8dSAndroid Build Coastguard Worker 221*cda5da8dSAndroid Build Coastguard Worker# The child indices of heap index pos are already heaps, and we want to make 222*cda5da8dSAndroid Build Coastguard Worker# a heap at index pos too. We do this by bubbling the smaller child of 223*cda5da8dSAndroid Build Coastguard Worker# pos up (and so on with that child's children, etc) until hitting a leaf, 224*cda5da8dSAndroid Build Coastguard Worker# then using _siftdown to move the oddball originally at index pos into place. 225*cda5da8dSAndroid Build Coastguard Worker# 226*cda5da8dSAndroid Build Coastguard Worker# We *could* break out of the loop as soon as we find a pos where newitem <= 227*cda5da8dSAndroid Build Coastguard Worker# both its children, but turns out that's not a good idea, and despite that 228*cda5da8dSAndroid Build Coastguard Worker# many books write the algorithm that way. During a heap pop, the last array 229*cda5da8dSAndroid Build Coastguard Worker# element is sifted in, and that tends to be large, so that comparing it 230*cda5da8dSAndroid Build Coastguard Worker# against values starting from the root usually doesn't pay (= usually doesn't 231*cda5da8dSAndroid Build Coastguard Worker# get us out of the loop early). See Knuth, Volume 3, where this is 232*cda5da8dSAndroid Build Coastguard Worker# explained and quantified in an exercise. 233*cda5da8dSAndroid Build Coastguard Worker# 234*cda5da8dSAndroid Build Coastguard Worker# Cutting the # of comparisons is important, since these routines have no 235*cda5da8dSAndroid Build Coastguard Worker# way to extract "the priority" from an array element, so that intelligence 236*cda5da8dSAndroid Build Coastguard Worker# is likely to be hiding in custom comparison methods, or in array elements 237*cda5da8dSAndroid Build Coastguard Worker# storing (priority, record) tuples. Comparisons are thus potentially 238*cda5da8dSAndroid Build Coastguard Worker# expensive. 239*cda5da8dSAndroid Build Coastguard Worker# 240*cda5da8dSAndroid Build Coastguard Worker# On random arrays of length 1000, making this change cut the number of 241*cda5da8dSAndroid Build Coastguard Worker# comparisons made by heapify() a little, and those made by exhaustive 242*cda5da8dSAndroid Build Coastguard Worker# heappop() a lot, in accord with theory. Here are typical results from 3 243*cda5da8dSAndroid Build Coastguard Worker# runs (3 just to demonstrate how small the variance is): 244*cda5da8dSAndroid Build Coastguard Worker# 245*cda5da8dSAndroid Build Coastguard Worker# Compares needed by heapify Compares needed by 1000 heappops 246*cda5da8dSAndroid Build Coastguard Worker# -------------------------- -------------------------------- 247*cda5da8dSAndroid Build Coastguard Worker# 1837 cut to 1663 14996 cut to 8680 248*cda5da8dSAndroid Build Coastguard Worker# 1855 cut to 1659 14966 cut to 8678 249*cda5da8dSAndroid Build Coastguard Worker# 1847 cut to 1660 15024 cut to 8703 250*cda5da8dSAndroid Build Coastguard Worker# 251*cda5da8dSAndroid Build Coastguard Worker# Building the heap by using heappush() 1000 times instead required 252*cda5da8dSAndroid Build Coastguard Worker# 2198, 2148, and 2219 compares: heapify() is more efficient, when 253*cda5da8dSAndroid Build Coastguard Worker# you can use it. 254*cda5da8dSAndroid Build Coastguard Worker# 255*cda5da8dSAndroid Build Coastguard Worker# The total compares needed by list.sort() on the same lists were 8627, 256*cda5da8dSAndroid Build Coastguard Worker# 8627, and 8632 (this should be compared to the sum of heapify() and 257*cda5da8dSAndroid Build Coastguard Worker# heappop() compares): list.sort() is (unsurprisingly!) more efficient 258*cda5da8dSAndroid Build Coastguard Worker# for sorting. 259*cda5da8dSAndroid Build Coastguard Worker 260*cda5da8dSAndroid Build Coastguard Workerdef _siftup(heap, pos): 261*cda5da8dSAndroid Build Coastguard Worker endpos = len(heap) 262*cda5da8dSAndroid Build Coastguard Worker startpos = pos 263*cda5da8dSAndroid Build Coastguard Worker newitem = heap[pos] 264*cda5da8dSAndroid Build Coastguard Worker # Bubble up the smaller child until hitting a leaf. 265*cda5da8dSAndroid Build Coastguard Worker childpos = 2*pos + 1 # leftmost child position 266*cda5da8dSAndroid Build Coastguard Worker while childpos < endpos: 267*cda5da8dSAndroid Build Coastguard Worker # Set childpos to index of smaller child. 268*cda5da8dSAndroid Build Coastguard Worker rightpos = childpos + 1 269*cda5da8dSAndroid Build Coastguard Worker if rightpos < endpos and not heap[childpos] < heap[rightpos]: 270*cda5da8dSAndroid Build Coastguard Worker childpos = rightpos 271*cda5da8dSAndroid Build Coastguard Worker # Move the smaller child up. 272*cda5da8dSAndroid Build Coastguard Worker heap[pos] = heap[childpos] 273*cda5da8dSAndroid Build Coastguard Worker pos = childpos 274*cda5da8dSAndroid Build Coastguard Worker childpos = 2*pos + 1 275*cda5da8dSAndroid Build Coastguard Worker # The leaf at pos is empty now. Put newitem there, and bubble it up 276*cda5da8dSAndroid Build Coastguard Worker # to its final resting place (by sifting its parents down). 277*cda5da8dSAndroid Build Coastguard Worker heap[pos] = newitem 278*cda5da8dSAndroid Build Coastguard Worker _siftdown(heap, startpos, pos) 279*cda5da8dSAndroid Build Coastguard Worker 280*cda5da8dSAndroid Build Coastguard Workerdef _siftdown_max(heap, startpos, pos): 281*cda5da8dSAndroid Build Coastguard Worker 'Maxheap variant of _siftdown' 282*cda5da8dSAndroid Build Coastguard Worker newitem = heap[pos] 283*cda5da8dSAndroid Build Coastguard Worker # Follow the path to the root, moving parents down until finding a place 284*cda5da8dSAndroid Build Coastguard Worker # newitem fits. 285*cda5da8dSAndroid Build Coastguard Worker while pos > startpos: 286*cda5da8dSAndroid Build Coastguard Worker parentpos = (pos - 1) >> 1 287*cda5da8dSAndroid Build Coastguard Worker parent = heap[parentpos] 288*cda5da8dSAndroid Build Coastguard Worker if parent < newitem: 289*cda5da8dSAndroid Build Coastguard Worker heap[pos] = parent 290*cda5da8dSAndroid Build Coastguard Worker pos = parentpos 291*cda5da8dSAndroid Build Coastguard Worker continue 292*cda5da8dSAndroid Build Coastguard Worker break 293*cda5da8dSAndroid Build Coastguard Worker heap[pos] = newitem 294*cda5da8dSAndroid Build Coastguard Worker 295*cda5da8dSAndroid Build Coastguard Workerdef _siftup_max(heap, pos): 296*cda5da8dSAndroid Build Coastguard Worker 'Maxheap variant of _siftup' 297*cda5da8dSAndroid Build Coastguard Worker endpos = len(heap) 298*cda5da8dSAndroid Build Coastguard Worker startpos = pos 299*cda5da8dSAndroid Build Coastguard Worker newitem = heap[pos] 300*cda5da8dSAndroid Build Coastguard Worker # Bubble up the larger child until hitting a leaf. 301*cda5da8dSAndroid Build Coastguard Worker childpos = 2*pos + 1 # leftmost child position 302*cda5da8dSAndroid Build Coastguard Worker while childpos < endpos: 303*cda5da8dSAndroid Build Coastguard Worker # Set childpos to index of larger child. 304*cda5da8dSAndroid Build Coastguard Worker rightpos = childpos + 1 305*cda5da8dSAndroid Build Coastguard Worker if rightpos < endpos and not heap[rightpos] < heap[childpos]: 306*cda5da8dSAndroid Build Coastguard Worker childpos = rightpos 307*cda5da8dSAndroid Build Coastguard Worker # Move the larger child up. 308*cda5da8dSAndroid Build Coastguard Worker heap[pos] = heap[childpos] 309*cda5da8dSAndroid Build Coastguard Worker pos = childpos 310*cda5da8dSAndroid Build Coastguard Worker childpos = 2*pos + 1 311*cda5da8dSAndroid Build Coastguard Worker # The leaf at pos is empty now. Put newitem there, and bubble it up 312*cda5da8dSAndroid Build Coastguard Worker # to its final resting place (by sifting its parents down). 313*cda5da8dSAndroid Build Coastguard Worker heap[pos] = newitem 314*cda5da8dSAndroid Build Coastguard Worker _siftdown_max(heap, startpos, pos) 315*cda5da8dSAndroid Build Coastguard Worker 316*cda5da8dSAndroid Build Coastguard Workerdef merge(*iterables, key=None, reverse=False): 317*cda5da8dSAndroid Build Coastguard Worker '''Merge multiple sorted inputs into a single sorted output. 318*cda5da8dSAndroid Build Coastguard Worker 319*cda5da8dSAndroid Build Coastguard Worker Similar to sorted(itertools.chain(*iterables)) but returns a generator, 320*cda5da8dSAndroid Build Coastguard Worker does not pull the data into memory all at once, and assumes that each of 321*cda5da8dSAndroid Build Coastguard Worker the input streams is already sorted (smallest to largest). 322*cda5da8dSAndroid Build Coastguard Worker 323*cda5da8dSAndroid Build Coastguard Worker >>> list(merge([1,3,5,7], [0,2,4,8], [5,10,15,20], [], [25])) 324*cda5da8dSAndroid Build Coastguard Worker [0, 1, 2, 3, 4, 5, 5, 7, 8, 10, 15, 20, 25] 325*cda5da8dSAndroid Build Coastguard Worker 326*cda5da8dSAndroid Build Coastguard Worker If *key* is not None, applies a key function to each element to determine 327*cda5da8dSAndroid Build Coastguard Worker its sort order. 328*cda5da8dSAndroid Build Coastguard Worker 329*cda5da8dSAndroid Build Coastguard Worker >>> list(merge(['dog', 'horse'], ['cat', 'fish', 'kangaroo'], key=len)) 330*cda5da8dSAndroid Build Coastguard Worker ['dog', 'cat', 'fish', 'horse', 'kangaroo'] 331*cda5da8dSAndroid Build Coastguard Worker 332*cda5da8dSAndroid Build Coastguard Worker ''' 333*cda5da8dSAndroid Build Coastguard Worker 334*cda5da8dSAndroid Build Coastguard Worker h = [] 335*cda5da8dSAndroid Build Coastguard Worker h_append = h.append 336*cda5da8dSAndroid Build Coastguard Worker 337*cda5da8dSAndroid Build Coastguard Worker if reverse: 338*cda5da8dSAndroid Build Coastguard Worker _heapify = _heapify_max 339*cda5da8dSAndroid Build Coastguard Worker _heappop = _heappop_max 340*cda5da8dSAndroid Build Coastguard Worker _heapreplace = _heapreplace_max 341*cda5da8dSAndroid Build Coastguard Worker direction = -1 342*cda5da8dSAndroid Build Coastguard Worker else: 343*cda5da8dSAndroid Build Coastguard Worker _heapify = heapify 344*cda5da8dSAndroid Build Coastguard Worker _heappop = heappop 345*cda5da8dSAndroid Build Coastguard Worker _heapreplace = heapreplace 346*cda5da8dSAndroid Build Coastguard Worker direction = 1 347*cda5da8dSAndroid Build Coastguard Worker 348*cda5da8dSAndroid Build Coastguard Worker if key is None: 349*cda5da8dSAndroid Build Coastguard Worker for order, it in enumerate(map(iter, iterables)): 350*cda5da8dSAndroid Build Coastguard Worker try: 351*cda5da8dSAndroid Build Coastguard Worker next = it.__next__ 352*cda5da8dSAndroid Build Coastguard Worker h_append([next(), order * direction, next]) 353*cda5da8dSAndroid Build Coastguard Worker except StopIteration: 354*cda5da8dSAndroid Build Coastguard Worker pass 355*cda5da8dSAndroid Build Coastguard Worker _heapify(h) 356*cda5da8dSAndroid Build Coastguard Worker while len(h) > 1: 357*cda5da8dSAndroid Build Coastguard Worker try: 358*cda5da8dSAndroid Build Coastguard Worker while True: 359*cda5da8dSAndroid Build Coastguard Worker value, order, next = s = h[0] 360*cda5da8dSAndroid Build Coastguard Worker yield value 361*cda5da8dSAndroid Build Coastguard Worker s[0] = next() # raises StopIteration when exhausted 362*cda5da8dSAndroid Build Coastguard Worker _heapreplace(h, s) # restore heap condition 363*cda5da8dSAndroid Build Coastguard Worker except StopIteration: 364*cda5da8dSAndroid Build Coastguard Worker _heappop(h) # remove empty iterator 365*cda5da8dSAndroid Build Coastguard Worker if h: 366*cda5da8dSAndroid Build Coastguard Worker # fast case when only a single iterator remains 367*cda5da8dSAndroid Build Coastguard Worker value, order, next = h[0] 368*cda5da8dSAndroid Build Coastguard Worker yield value 369*cda5da8dSAndroid Build Coastguard Worker yield from next.__self__ 370*cda5da8dSAndroid Build Coastguard Worker return 371*cda5da8dSAndroid Build Coastguard Worker 372*cda5da8dSAndroid Build Coastguard Worker for order, it in enumerate(map(iter, iterables)): 373*cda5da8dSAndroid Build Coastguard Worker try: 374*cda5da8dSAndroid Build Coastguard Worker next = it.__next__ 375*cda5da8dSAndroid Build Coastguard Worker value = next() 376*cda5da8dSAndroid Build Coastguard Worker h_append([key(value), order * direction, value, next]) 377*cda5da8dSAndroid Build Coastguard Worker except StopIteration: 378*cda5da8dSAndroid Build Coastguard Worker pass 379*cda5da8dSAndroid Build Coastguard Worker _heapify(h) 380*cda5da8dSAndroid Build Coastguard Worker while len(h) > 1: 381*cda5da8dSAndroid Build Coastguard Worker try: 382*cda5da8dSAndroid Build Coastguard Worker while True: 383*cda5da8dSAndroid Build Coastguard Worker key_value, order, value, next = s = h[0] 384*cda5da8dSAndroid Build Coastguard Worker yield value 385*cda5da8dSAndroid Build Coastguard Worker value = next() 386*cda5da8dSAndroid Build Coastguard Worker s[0] = key(value) 387*cda5da8dSAndroid Build Coastguard Worker s[2] = value 388*cda5da8dSAndroid Build Coastguard Worker _heapreplace(h, s) 389*cda5da8dSAndroid Build Coastguard Worker except StopIteration: 390*cda5da8dSAndroid Build Coastguard Worker _heappop(h) 391*cda5da8dSAndroid Build Coastguard Worker if h: 392*cda5da8dSAndroid Build Coastguard Worker key_value, order, value, next = h[0] 393*cda5da8dSAndroid Build Coastguard Worker yield value 394*cda5da8dSAndroid Build Coastguard Worker yield from next.__self__ 395*cda5da8dSAndroid Build Coastguard Worker 396*cda5da8dSAndroid Build Coastguard Worker 397*cda5da8dSAndroid Build Coastguard Worker# Algorithm notes for nlargest() and nsmallest() 398*cda5da8dSAndroid Build Coastguard Worker# ============================================== 399*cda5da8dSAndroid Build Coastguard Worker# 400*cda5da8dSAndroid Build Coastguard Worker# Make a single pass over the data while keeping the k most extreme values 401*cda5da8dSAndroid Build Coastguard Worker# in a heap. Memory consumption is limited to keeping k values in a list. 402*cda5da8dSAndroid Build Coastguard Worker# 403*cda5da8dSAndroid Build Coastguard Worker# Measured performance for random inputs: 404*cda5da8dSAndroid Build Coastguard Worker# 405*cda5da8dSAndroid Build Coastguard Worker# number of comparisons 406*cda5da8dSAndroid Build Coastguard Worker# n inputs k-extreme values (average of 5 trials) % more than min() 407*cda5da8dSAndroid Build Coastguard Worker# ------------- ---------------- --------------------- ----------------- 408*cda5da8dSAndroid Build Coastguard Worker# 1,000 100 3,317 231.7% 409*cda5da8dSAndroid Build Coastguard Worker# 10,000 100 14,046 40.5% 410*cda5da8dSAndroid Build Coastguard Worker# 100,000 100 105,749 5.7% 411*cda5da8dSAndroid Build Coastguard Worker# 1,000,000 100 1,007,751 0.8% 412*cda5da8dSAndroid Build Coastguard Worker# 10,000,000 100 10,009,401 0.1% 413*cda5da8dSAndroid Build Coastguard Worker# 414*cda5da8dSAndroid Build Coastguard Worker# Theoretical number of comparisons for k smallest of n random inputs: 415*cda5da8dSAndroid Build Coastguard Worker# 416*cda5da8dSAndroid Build Coastguard Worker# Step Comparisons Action 417*cda5da8dSAndroid Build Coastguard Worker# ---- -------------------------- --------------------------- 418*cda5da8dSAndroid Build Coastguard Worker# 1 1.66 * k heapify the first k-inputs 419*cda5da8dSAndroid Build Coastguard Worker# 2 n - k compare remaining elements to top of heap 420*cda5da8dSAndroid Build Coastguard Worker# 3 k * (1 + lg2(k)) * ln(n/k) replace the topmost value on the heap 421*cda5da8dSAndroid Build Coastguard Worker# 4 k * lg2(k) - (k/2) final sort of the k most extreme values 422*cda5da8dSAndroid Build Coastguard Worker# 423*cda5da8dSAndroid Build Coastguard Worker# Combining and simplifying for a rough estimate gives: 424*cda5da8dSAndroid Build Coastguard Worker# 425*cda5da8dSAndroid Build Coastguard Worker# comparisons = n + k * (log(k, 2) * log(n/k) + log(k, 2) + log(n/k)) 426*cda5da8dSAndroid Build Coastguard Worker# 427*cda5da8dSAndroid Build Coastguard Worker# Computing the number of comparisons for step 3: 428*cda5da8dSAndroid Build Coastguard Worker# ----------------------------------------------- 429*cda5da8dSAndroid Build Coastguard Worker# * For the i-th new value from the iterable, the probability of being in the 430*cda5da8dSAndroid Build Coastguard Worker# k most extreme values is k/i. For example, the probability of the 101st 431*cda5da8dSAndroid Build Coastguard Worker# value seen being in the 100 most extreme values is 100/101. 432*cda5da8dSAndroid Build Coastguard Worker# * If the value is a new extreme value, the cost of inserting it into the 433*cda5da8dSAndroid Build Coastguard Worker# heap is 1 + log(k, 2). 434*cda5da8dSAndroid Build Coastguard Worker# * The probability times the cost gives: 435*cda5da8dSAndroid Build Coastguard Worker# (k/i) * (1 + log(k, 2)) 436*cda5da8dSAndroid Build Coastguard Worker# * Summing across the remaining n-k elements gives: 437*cda5da8dSAndroid Build Coastguard Worker# sum((k/i) * (1 + log(k, 2)) for i in range(k+1, n+1)) 438*cda5da8dSAndroid Build Coastguard Worker# * This reduces to: 439*cda5da8dSAndroid Build Coastguard Worker# (H(n) - H(k)) * k * (1 + log(k, 2)) 440*cda5da8dSAndroid Build Coastguard Worker# * Where H(n) is the n-th harmonic number estimated by: 441*cda5da8dSAndroid Build Coastguard Worker# gamma = 0.5772156649 442*cda5da8dSAndroid Build Coastguard Worker# H(n) = log(n, e) + gamma + 1 / (2 * n) 443*cda5da8dSAndroid Build Coastguard Worker# http://en.wikipedia.org/wiki/Harmonic_series_(mathematics)#Rate_of_divergence 444*cda5da8dSAndroid Build Coastguard Worker# * Substituting the H(n) formula: 445*cda5da8dSAndroid Build Coastguard Worker# comparisons = k * (1 + log(k, 2)) * (log(n/k, e) + (1/n - 1/k) / 2) 446*cda5da8dSAndroid Build Coastguard Worker# 447*cda5da8dSAndroid Build Coastguard Worker# Worst-case for step 3: 448*cda5da8dSAndroid Build Coastguard Worker# ---------------------- 449*cda5da8dSAndroid Build Coastguard Worker# In the worst case, the input data is reversed sorted so that every new element 450*cda5da8dSAndroid Build Coastguard Worker# must be inserted in the heap: 451*cda5da8dSAndroid Build Coastguard Worker# 452*cda5da8dSAndroid Build Coastguard Worker# comparisons = 1.66 * k + log(k, 2) * (n - k) 453*cda5da8dSAndroid Build Coastguard Worker# 454*cda5da8dSAndroid Build Coastguard Worker# Alternative Algorithms 455*cda5da8dSAndroid Build Coastguard Worker# ---------------------- 456*cda5da8dSAndroid Build Coastguard Worker# Other algorithms were not used because they: 457*cda5da8dSAndroid Build Coastguard Worker# 1) Took much more auxiliary memory, 458*cda5da8dSAndroid Build Coastguard Worker# 2) Made multiple passes over the data. 459*cda5da8dSAndroid Build Coastguard Worker# 3) Made more comparisons in common cases (small k, large n, semi-random input). 460*cda5da8dSAndroid Build Coastguard Worker# See the more detailed comparison of approach at: 461*cda5da8dSAndroid Build Coastguard Worker# http://code.activestate.com/recipes/577573-compare-algorithms-for-heapqsmallest 462*cda5da8dSAndroid Build Coastguard Worker 463*cda5da8dSAndroid Build Coastguard Workerdef nsmallest(n, iterable, key=None): 464*cda5da8dSAndroid Build Coastguard Worker """Find the n smallest elements in a dataset. 465*cda5da8dSAndroid Build Coastguard Worker 466*cda5da8dSAndroid Build Coastguard Worker Equivalent to: sorted(iterable, key=key)[:n] 467*cda5da8dSAndroid Build Coastguard Worker """ 468*cda5da8dSAndroid Build Coastguard Worker 469*cda5da8dSAndroid Build Coastguard Worker # Short-cut for n==1 is to use min() 470*cda5da8dSAndroid Build Coastguard Worker if n == 1: 471*cda5da8dSAndroid Build Coastguard Worker it = iter(iterable) 472*cda5da8dSAndroid Build Coastguard Worker sentinel = object() 473*cda5da8dSAndroid Build Coastguard Worker result = min(it, default=sentinel, key=key) 474*cda5da8dSAndroid Build Coastguard Worker return [] if result is sentinel else [result] 475*cda5da8dSAndroid Build Coastguard Worker 476*cda5da8dSAndroid Build Coastguard Worker # When n>=size, it's faster to use sorted() 477*cda5da8dSAndroid Build Coastguard Worker try: 478*cda5da8dSAndroid Build Coastguard Worker size = len(iterable) 479*cda5da8dSAndroid Build Coastguard Worker except (TypeError, AttributeError): 480*cda5da8dSAndroid Build Coastguard Worker pass 481*cda5da8dSAndroid Build Coastguard Worker else: 482*cda5da8dSAndroid Build Coastguard Worker if n >= size: 483*cda5da8dSAndroid Build Coastguard Worker return sorted(iterable, key=key)[:n] 484*cda5da8dSAndroid Build Coastguard Worker 485*cda5da8dSAndroid Build Coastguard Worker # When key is none, use simpler decoration 486*cda5da8dSAndroid Build Coastguard Worker if key is None: 487*cda5da8dSAndroid Build Coastguard Worker it = iter(iterable) 488*cda5da8dSAndroid Build Coastguard Worker # put the range(n) first so that zip() doesn't 489*cda5da8dSAndroid Build Coastguard Worker # consume one too many elements from the iterator 490*cda5da8dSAndroid Build Coastguard Worker result = [(elem, i) for i, elem in zip(range(n), it)] 491*cda5da8dSAndroid Build Coastguard Worker if not result: 492*cda5da8dSAndroid Build Coastguard Worker return result 493*cda5da8dSAndroid Build Coastguard Worker _heapify_max(result) 494*cda5da8dSAndroid Build Coastguard Worker top = result[0][0] 495*cda5da8dSAndroid Build Coastguard Worker order = n 496*cda5da8dSAndroid Build Coastguard Worker _heapreplace = _heapreplace_max 497*cda5da8dSAndroid Build Coastguard Worker for elem in it: 498*cda5da8dSAndroid Build Coastguard Worker if elem < top: 499*cda5da8dSAndroid Build Coastguard Worker _heapreplace(result, (elem, order)) 500*cda5da8dSAndroid Build Coastguard Worker top, _order = result[0] 501*cda5da8dSAndroid Build Coastguard Worker order += 1 502*cda5da8dSAndroid Build Coastguard Worker result.sort() 503*cda5da8dSAndroid Build Coastguard Worker return [elem for (elem, order) in result] 504*cda5da8dSAndroid Build Coastguard Worker 505*cda5da8dSAndroid Build Coastguard Worker # General case, slowest method 506*cda5da8dSAndroid Build Coastguard Worker it = iter(iterable) 507*cda5da8dSAndroid Build Coastguard Worker result = [(key(elem), i, elem) for i, elem in zip(range(n), it)] 508*cda5da8dSAndroid Build Coastguard Worker if not result: 509*cda5da8dSAndroid Build Coastguard Worker return result 510*cda5da8dSAndroid Build Coastguard Worker _heapify_max(result) 511*cda5da8dSAndroid Build Coastguard Worker top = result[0][0] 512*cda5da8dSAndroid Build Coastguard Worker order = n 513*cda5da8dSAndroid Build Coastguard Worker _heapreplace = _heapreplace_max 514*cda5da8dSAndroid Build Coastguard Worker for elem in it: 515*cda5da8dSAndroid Build Coastguard Worker k = key(elem) 516*cda5da8dSAndroid Build Coastguard Worker if k < top: 517*cda5da8dSAndroid Build Coastguard Worker _heapreplace(result, (k, order, elem)) 518*cda5da8dSAndroid Build Coastguard Worker top, _order, _elem = result[0] 519*cda5da8dSAndroid Build Coastguard Worker order += 1 520*cda5da8dSAndroid Build Coastguard Worker result.sort() 521*cda5da8dSAndroid Build Coastguard Worker return [elem for (k, order, elem) in result] 522*cda5da8dSAndroid Build Coastguard Worker 523*cda5da8dSAndroid Build Coastguard Workerdef nlargest(n, iterable, key=None): 524*cda5da8dSAndroid Build Coastguard Worker """Find the n largest elements in a dataset. 525*cda5da8dSAndroid Build Coastguard Worker 526*cda5da8dSAndroid Build Coastguard Worker Equivalent to: sorted(iterable, key=key, reverse=True)[:n] 527*cda5da8dSAndroid Build Coastguard Worker """ 528*cda5da8dSAndroid Build Coastguard Worker 529*cda5da8dSAndroid Build Coastguard Worker # Short-cut for n==1 is to use max() 530*cda5da8dSAndroid Build Coastguard Worker if n == 1: 531*cda5da8dSAndroid Build Coastguard Worker it = iter(iterable) 532*cda5da8dSAndroid Build Coastguard Worker sentinel = object() 533*cda5da8dSAndroid Build Coastguard Worker result = max(it, default=sentinel, key=key) 534*cda5da8dSAndroid Build Coastguard Worker return [] if result is sentinel else [result] 535*cda5da8dSAndroid Build Coastguard Worker 536*cda5da8dSAndroid Build Coastguard Worker # When n>=size, it's faster to use sorted() 537*cda5da8dSAndroid Build Coastguard Worker try: 538*cda5da8dSAndroid Build Coastguard Worker size = len(iterable) 539*cda5da8dSAndroid Build Coastguard Worker except (TypeError, AttributeError): 540*cda5da8dSAndroid Build Coastguard Worker pass 541*cda5da8dSAndroid Build Coastguard Worker else: 542*cda5da8dSAndroid Build Coastguard Worker if n >= size: 543*cda5da8dSAndroid Build Coastguard Worker return sorted(iterable, key=key, reverse=True)[:n] 544*cda5da8dSAndroid Build Coastguard Worker 545*cda5da8dSAndroid Build Coastguard Worker # When key is none, use simpler decoration 546*cda5da8dSAndroid Build Coastguard Worker if key is None: 547*cda5da8dSAndroid Build Coastguard Worker it = iter(iterable) 548*cda5da8dSAndroid Build Coastguard Worker result = [(elem, i) for i, elem in zip(range(0, -n, -1), it)] 549*cda5da8dSAndroid Build Coastguard Worker if not result: 550*cda5da8dSAndroid Build Coastguard Worker return result 551*cda5da8dSAndroid Build Coastguard Worker heapify(result) 552*cda5da8dSAndroid Build Coastguard Worker top = result[0][0] 553*cda5da8dSAndroid Build Coastguard Worker order = -n 554*cda5da8dSAndroid Build Coastguard Worker _heapreplace = heapreplace 555*cda5da8dSAndroid Build Coastguard Worker for elem in it: 556*cda5da8dSAndroid Build Coastguard Worker if top < elem: 557*cda5da8dSAndroid Build Coastguard Worker _heapreplace(result, (elem, order)) 558*cda5da8dSAndroid Build Coastguard Worker top, _order = result[0] 559*cda5da8dSAndroid Build Coastguard Worker order -= 1 560*cda5da8dSAndroid Build Coastguard Worker result.sort(reverse=True) 561*cda5da8dSAndroid Build Coastguard Worker return [elem for (elem, order) in result] 562*cda5da8dSAndroid Build Coastguard Worker 563*cda5da8dSAndroid Build Coastguard Worker # General case, slowest method 564*cda5da8dSAndroid Build Coastguard Worker it = iter(iterable) 565*cda5da8dSAndroid Build Coastguard Worker result = [(key(elem), i, elem) for i, elem in zip(range(0, -n, -1), it)] 566*cda5da8dSAndroid Build Coastguard Worker if not result: 567*cda5da8dSAndroid Build Coastguard Worker return result 568*cda5da8dSAndroid Build Coastguard Worker heapify(result) 569*cda5da8dSAndroid Build Coastguard Worker top = result[0][0] 570*cda5da8dSAndroid Build Coastguard Worker order = -n 571*cda5da8dSAndroid Build Coastguard Worker _heapreplace = heapreplace 572*cda5da8dSAndroid Build Coastguard Worker for elem in it: 573*cda5da8dSAndroid Build Coastguard Worker k = key(elem) 574*cda5da8dSAndroid Build Coastguard Worker if top < k: 575*cda5da8dSAndroid Build Coastguard Worker _heapreplace(result, (k, order, elem)) 576*cda5da8dSAndroid Build Coastguard Worker top, _order, _elem = result[0] 577*cda5da8dSAndroid Build Coastguard Worker order -= 1 578*cda5da8dSAndroid Build Coastguard Worker result.sort(reverse=True) 579*cda5da8dSAndroid Build Coastguard Worker return [elem for (k, order, elem) in result] 580*cda5da8dSAndroid Build Coastguard Worker 581*cda5da8dSAndroid Build Coastguard Worker# If available, use C implementation 582*cda5da8dSAndroid Build Coastguard Workertry: 583*cda5da8dSAndroid Build Coastguard Worker from _heapq import * 584*cda5da8dSAndroid Build Coastguard Workerexcept ImportError: 585*cda5da8dSAndroid Build Coastguard Worker pass 586*cda5da8dSAndroid Build Coastguard Workertry: 587*cda5da8dSAndroid Build Coastguard Worker from _heapq import _heapreplace_max 588*cda5da8dSAndroid Build Coastguard Workerexcept ImportError: 589*cda5da8dSAndroid Build Coastguard Worker pass 590*cda5da8dSAndroid Build Coastguard Workertry: 591*cda5da8dSAndroid Build Coastguard Worker from _heapq import _heapify_max 592*cda5da8dSAndroid Build Coastguard Workerexcept ImportError: 593*cda5da8dSAndroid Build Coastguard Worker pass 594*cda5da8dSAndroid Build Coastguard Workertry: 595*cda5da8dSAndroid Build Coastguard Worker from _heapq import _heappop_max 596*cda5da8dSAndroid Build Coastguard Workerexcept ImportError: 597*cda5da8dSAndroid Build Coastguard Worker pass 598*cda5da8dSAndroid Build Coastguard Worker 599*cda5da8dSAndroid Build Coastguard Worker 600*cda5da8dSAndroid Build Coastguard Workerif __name__ == "__main__": 601*cda5da8dSAndroid Build Coastguard Worker 602*cda5da8dSAndroid Build Coastguard Worker import doctest # pragma: no cover 603*cda5da8dSAndroid Build Coastguard Worker print(doctest.testmod()) # pragma: no cover 604