[Python-checkins] python/dist/src/Lib heapq.py,1.6,1.7

tim_one@users.sourceforge.net tim_one@users.sourceforge.net
Fri, 02 Aug 2002 14:48:08 -0700


Update of /cvsroot/python/python/dist/src/Lib
In directory usw-pr-cvs1:/tmp/cvs-serv23987/python/Lib

Modified Files:
	heapq.py 
Log Message:
Hmm!  I thought I checked this in before!  Oh well.

Added new heapify() function, which transforms an arbitrary list into a
heap in linear time; that's a fundamental tool for using heaps in real
life <wink>.

Added heapyify() test.  Added a "less naive" N-best algorithm to the test
suite, and noted that this could actually go much faster (building on
heapify()) if we had max-heaps instead of min-heaps (the iterative method
is appropriate when all the data isn't known in advance, but when it is
known in advance the tradeoffs get murkier).


Index: heapq.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Lib/heapq.py,v
retrieving revision 1.6
retrieving revision 1.7
diff -C2 -d -r1.6 -r1.7
*** heapq.py	2 Aug 2002 20:23:56 -0000	1.6
--- heapq.py	2 Aug 2002 21:48:06 -0000	1.7
***************
*** 14,17 ****
--- 14,18 ----
  item = heappop(heap) # pops the smallest item from the heap
  item = heap[0]       # smallest item on the heap without popping it
+ heapify(heap)        # transform list into a heap, in-place, in linear time
  
  Our API differs from textbook heap algorithms as follows:
***************
*** 137,149 ****
      heap[pos] = item
  
! def heappop(heap):
!     """Pop the smallest item off the heap, maintaining the heap invariant."""
!     endpos = len(heap) - 1
!     if endpos <= 0:
!         return heap.pop()
!     returnitem = heap[0]
!     item = heap.pop()
!     pos = 0
!     # Sift item into position, down from the root, moving the smaller
      # child up, until finding pos such that item <= pos's children.
      childpos = 2*pos + 1    # leftmost child position
--- 138,148 ----
      heap[pos] = item
  
! # The child indices of heap index pos are already heaps, and we want to make
! # a heap at index pos too.
! def _siftdown(heap, pos):
!     endpos = len(heap)
!     assert pos < endpos
!     item = heap[pos]
!     # Sift item into position, down from pos, moving the smaller
      # child up, until finding pos such that item <= pos's children.
      childpos = 2*pos + 1    # leftmost child position
***************
*** 165,169 ****
--- 164,189 ----
          childpos = 2*pos + 1
      heap[pos] = item
+ 
+ def heappop(heap):
+     """Pop the smallest item off the heap, maintaining the heap invariant."""
+     lastelt = heap.pop()    # raises appropriate IndexError if heap is empty
+     if heap:
+         returnitem = heap[0]
+         heap[0] = lastelt
+         _siftdown(heap, 0)
+     else:
+         returnitem = lastelt
      return returnitem
+ 
+ def heapify(heap):
+     """Transform list heap into a heap, in-place, in O(len(heap)) time."""
+     n = len(heap)
+     # Transform bottom-up.  The largest index there's any point to looking at
+     # is the largest with a child index in-range, so must have 2*i + 1 < n,
+     # or i < (n-1)/2.  If n is even = 2*j, this is (2*j-1)/2 = j-1/2 so
+     # j-1 is the largest, which is n//2 - 1.  If n is odd = 2*j+1, this is
+     # (2*j+1-1)/2 = j so j-1 is the largest, and that's again n//2-1.
+     for i in xrange(n//2 - 1, -1, -1):
+         _siftdown(heap, i)
  
  if __name__ == "__main__":