Ignore:
Timestamp:
Mar 19, 2014, 11:31:01 PM (11 years ago)
Author:
dmik
Message:

python: Merge vendor 2.7.6 to trunk.

Location:
python/trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • python/trunk

  • python/trunk/Doc/library/heapq.rst

    r2 r391  
    77.. sectionauthor:: Guido van Rossum <guido@python.org>
    88.. sectionauthor:: François Pinard
     9.. sectionauthor:: Raymond Hettinger
    910
    1011.. versionadded:: 2.3
     12
     13**Source code:** :source:`Lib/heapq.py`
     14
     15--------------
    1116
    1217This module provides an implementation of the heap queue algorithm, also known
    1318as the priority queue algorithm.
    1419
    15 Heaps are arrays for which ``heap[k] <= heap[2*k+1]`` and ``heap[k] <=
    16 heap[2*k+2]`` for all *k*, counting elements from zero.  For the sake of
    17 comparison, non-existing elements are considered to be infinite.  The
    18 interesting property of a heap is that ``heap[0]`` is always its smallest
    19 element.
     20Heaps are binary trees for which every parent node has a value less than or
     21equal to any of its children.  This implementation uses arrays for which
     22``heap[k] <= heap[2*k+1]`` and ``heap[k] <= heap[2*k+2]`` for all *k*, counting
     23elements from zero.  For the sake of comparison, non-existing elements are
     24considered to be infinite.  The interesting property of a heap is that its
     25smallest element is always the root, ``heap[0]``.
    2026
    2127The API below differs from textbook heap algorithms in two aspects: (a) We use
     
    6369   Pop and return the smallest item from the *heap*, and also push the new *item*.
    6470   The heap size doesn't change. If the heap is empty, :exc:`IndexError` is raised.
    65    This is more efficient than :func:`heappop` followed by  :func:`heappush`, and
    66    can be more appropriate when using a fixed-size heap.  Note that the value
    67    returned may be larger than *item*!  That constrains reasonable uses of this
    68    routine unless written as part of a conditional replacement::
    69 
    70       if item > heap[0]:
    71           item = heapreplace(heap, item)
    72 
    73 Example of use:
    74 
    75    >>> from heapq import heappush, heappop
    76    >>> heap = []
    77    >>> data = [1, 3, 5, 7, 9, 2, 4, 6, 8, 0]
    78    >>> for item in data:
    79    ...     heappush(heap, item)
    80    ...
    81    >>> ordered = []
    82    >>> while heap:
    83    ...     ordered.append(heappop(heap))
    84    ...
    85    >>> print ordered
    86    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    87    >>> data.sort()
    88    >>> print data == ordered
    89    True
    90 
    91 Using a heap to insert items at the correct place in a priority queue:
    92 
    93    >>> heap = []
    94    >>> data = [(1, 'J'), (4, 'N'), (3, 'H'), (2, 'O')]
    95    >>> for item in data:
    96    ...     heappush(heap, item)
    97    ...
    98    >>> while heap:
    99    ...     print heappop(heap)[1]
    100    J
    101    O
    102    H
    103    N
     71
     72   This one step operation is more efficient than a :func:`heappop` followed by
     73   :func:`heappush` and can be more appropriate when using a fixed-size heap.
     74   The pop/push combination always returns an element from the heap and replaces
     75   it with *item*.
     76
     77   The value returned may be larger than the *item* added.  If that isn't
     78   desired, consider using :func:`heappushpop` instead.  Its push/pop
     79   combination returns the smaller of the two values, leaving the larger value
     80   on the heap.
    10481
    10582
     
    152129
    153130
     131Basic Examples
     132--------------
     133
     134A `heapsort <http://en.wikipedia.org/wiki/Heapsort>`_ can be implemented by
     135pushing all values onto a heap and then popping off the smallest values one at a
     136time::
     137
     138   >>> def heapsort(iterable):
     139   ...     'Equivalent to sorted(iterable)'
     140   ...     h = []
     141   ...     for value in iterable:
     142   ...         heappush(h, value)
     143   ...     return [heappop(h) for i in range(len(h))]
     144   ...
     145   >>> heapsort([1, 3, 5, 7, 9, 2, 4, 6, 8, 0])
     146   [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
     147
     148Heap elements can be tuples.  This is useful for assigning comparison values
     149(such as task priorities) alongside the main record being tracked::
     150
     151    >>> h = []
     152    >>> heappush(h, (5, 'write code'))
     153    >>> heappush(h, (7, 'release product'))
     154    >>> heappush(h, (1, 'write spec'))
     155    >>> heappush(h, (3, 'create tests'))
     156    >>> heappop(h)
     157    (1, 'write spec')
     158
     159
     160Priority Queue Implementation Notes
     161-----------------------------------
     162
     163A `priority queue <http://en.wikipedia.org/wiki/Priority_queue>`_ is common use
     164for a heap, and it presents several implementation challenges:
     165
     166* Sort stability:  how do you get two tasks with equal priorities to be returned
     167  in the order they were originally added?
     168
     169* In the future with Python 3, tuple comparison breaks for (priority, task)
     170  pairs if the priorities are equal and the tasks do not have a default
     171  comparison order.
     172
     173* If the priority of a task changes, how do you move it to a new position in
     174  the heap?
     175
     176* Or if a pending task needs to be deleted, how do you find it and remove it
     177  from the queue?
     178
     179A solution to the first two challenges is to store entries as 3-element list
     180including the priority, an entry count, and the task.  The entry count serves as
     181a tie-breaker so that two tasks with the same priority are returned in the order
     182they were added. And since no two entry counts are the same, the tuple
     183comparison will never attempt to directly compare two tasks.
     184
     185The remaining challenges revolve around finding a pending task and making
     186changes to its priority or removing it entirely.  Finding a task can be done
     187with a dictionary pointing to an entry in the queue.
     188
     189Removing the entry or changing its priority is more difficult because it would
     190break the heap structure invariants.  So, a possible solution is to mark the
     191existing entry as removed and add a new entry with the revised priority::
     192
     193    pq = []                         # list of entries arranged in a heap
     194    entry_finder = {}               # mapping of tasks to entries
     195    REMOVED = '<removed-task>'      # placeholder for a removed task
     196    counter = itertools.count()     # unique sequence count
     197
     198    def add_task(task, priority=0):
     199        'Add a new task or update the priority of an existing task'
     200        if task in entry_finder:
     201            remove_task(task)
     202        count = next(counter)
     203        entry = [priority, count, task]
     204        entry_finder[task] = entry
     205        heappush(pq, entry)
     206
     207    def remove_task(task):
     208        'Mark an existing task as REMOVED.  Raise KeyError if not found.'
     209        entry = entry_finder.pop(task)
     210        entry[-1] = REMOVED
     211
     212    def pop_task():
     213        'Remove and return the lowest priority task. Raise KeyError if empty.'
     214        while pq:
     215            priority, count, task = heappop(pq)
     216            if task is not REMOVED:
     217                del entry_finder[task]
     218                return task
     219        raise KeyError('pop from an empty priority queue')
     220
     221
    154222Theory
    155223------
    156 
    157 (This explanation is due to François Pinard.  The Python code for this module
    158 was contributed by Kevin O'Connor.)
    159224
    160225Heaps are arrays for which ``a[k] <= a[2*k+1]`` and ``a[k] <= a[2*k+2]`` for all
     
    196261last 0'th element you extracted.  This is especially useful in simulation
    197262contexts, where the tree holds all incoming events, and the "win" condition
    198 means the smallest scheduled time.  When an event schedule other events for
     263means the smallest scheduled time.  When an event schedules other events for
    199264execution, they are scheduled into the future, so they can easily go into the
    200265heap.  So, a heap is a good structure for implementing schedulers (this is what
Note: See TracChangeset for help on using the changeset viewer.