diff --git a/Doc/library/heapq.rst b/Doc/library/heapq.rst index 26cffa7c643028..96e1135bfd97c6 100644 --- a/Doc/library/heapq.rst +++ b/Doc/library/heapq.rst @@ -214,6 +214,18 @@ time:: This is similar to ``sorted(iterable)``, but unlike :func:`sorted`, this implementation is not stable. +Using max-heap functions, a reverse (descending) heapsort is equally +straightforward:: + + >>> def heapsort_desc(iterable): + ... h = [] + ... for value in iterable: + ... heappush_max(h, value) + ... return [heappop_max(h) for i in range(len(h))] + ... + >>> heapsort_desc([1, 3, 5, 7, 9, 2, 4, 6, 8, 0]) + [9, 8, 7, 6, 5, 4, 3, 2, 1, 0] + Heap elements can be tuples. This is useful for assigning comparison values (such as task priorities) alongside the main record being tracked:: diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst index 772334f40a56fb..dc784a04719296 100644 --- a/Doc/whatsnew/3.14.rst +++ b/Doc/whatsnew/3.14.rst @@ -1387,14 +1387,19 @@ graphlib heapq ----- -* The :mod:`!heapq` module has improved support for working with max-heaps, - via the following new functions: - - * :func:`~heapq.heapify_max` - * :func:`~heapq.heappush_max` - * :func:`~heapq.heappop_max` - * :func:`~heapq.heapreplace_max` - * :func:`~heapq.heappushpop_max` +* The :mod:`!heapq` module now has full public support for max-heaps, + providing a symmetric API to the existing min-heap functions. + Max-heaps maintain the reverse invariant: ``heap[0]`` is always the + *largest* element. The new functions are: + + * :func:`~heapq.heapify_max`: Transform a list into a max-heap in-place + * :func:`~heapq.heappush_max`: Push an item onto a max-heap + * :func:`~heapq.heappop_max`: Pop the largest item from a max-heap + * :func:`~heapq.heapreplace_max`: Pop largest and push new item in one step + * :func:`~heapq.heappushpop_max`: Push new item and pop largest in one step + + These were previously available only as undocumented internal helpers. + (Contributed by Stan Ulbrych and Petr Viktorin in :gh:`110067`.) hmac diff --git a/Lib/heapq.py b/Lib/heapq.py index a3af6dc05bff37..58b879f75c9e53 100644 --- a/Lib/heapq.py +++ b/Lib/heapq.py @@ -5,7 +5,7 @@ non-existing elements are considered to be infinite. The interesting property of a heap is that a[0] is always its smallest element. -Usage: +Usage (min-heap): heap = [] # creates an empty heap heappush(heap, item) # pushes a new item on the heap @@ -17,6 +17,18 @@ item = heapreplace(heap, item) # pops and returns smallest item, and adds # new item; the heap size is unchanged +Usage (max-heap): + +heap = [] # creates an empty max-heap +heappush_max(heap, item) # pushes a new item on the max-heap +item = heappop_max(heap) # pops the largest item from the max-heap +item = heap[0] # largest item on the max-heap without popping it +heapify_max(x) # transforms list into a max-heap, in-place, in linear time +item = heappushpop_max(heap, item) # pushes a new item and then returns + # the largest item; the heap size is unchanged +item = heapreplace_max(heap, item) # pops and returns largest item, and adds + # new item; the heap size is unchanged + Our API differs from textbook heap algorithms as follows: - We use 0-based indexing. This makes the relationship between the diff --git a/Modules/_heapqmodule.c b/Modules/_heapqmodule.c index 05d01acd77109b..4ad12a69ea0f9b 100644 --- a/Modules/_heapqmodule.c +++ b/Modules/_heapqmodule.c @@ -658,7 +658,7 @@ all k, counting elements from 0. For the sake of comparison,\n\ non-existing elements are considered to be infinite. The interesting\n\ property of a heap is that a[0] is always its smallest element.\n\ \n\ -Usage:\n\ +Usage (min-heap):\n\ \n\ heap = [] # creates an empty heap\n\ heappush(heap, item) # pushes a new item on the heap\n\ @@ -668,6 +668,16 @@ heapify(x) # transforms list into a heap, in-place, in linear time\n\ item = heapreplace(heap, item) # pops and returns smallest item, and adds\n\ # new item; the heap size is unchanged\n\ \n\ +Usage (max-heap):\n\ +\n\ +heap = [] # creates an empty max-heap\n\ +heappush_max(heap, item) # pushes a new item on the max-heap\n\ +item = heappop_max(heap) # pops the largest item from the max-heap\n\ +item = heap[0] # largest item on the max-heap without popping it\n\ +heapify_max(x) # transforms list into a max-heap, in-place, in linear time\n\ +item = heapreplace_max(heap, item) # pops and returns largest item, and adds\n\ + # new item; the heap size is unchanged\n\ +\n\ Our API differs from textbook heap algorithms as follows:\n\ \n\ - We use 0-based indexing. This makes the relationship between the\n\