From 484793a5f5c4a102afa48c25942ca31e8e17a891 Mon Sep 17 00:00:00 2001 From: kunwar-vikrant Date: Thu, 19 Mar 2026 18:30:49 +0530 Subject: [PATCH 1/3] gh-110067: Improve max-heap documentation across heapq module - Add max-heap usage examples to module docstrings in both the Python (Lib/heapq.py) and C (Modules/_heapqmodule.c) implementations - Add descending heapsort example using max-heap functions to Doc/library/heapq.rst - Expand the What's New in 3.14 entry for heapq with descriptions of each new max-heap function, context about the change, and correct contributor attribution --- Doc/library/heapq.rst | 12 ++++++++++++ Doc/whatsnew/3.14.rst | 21 +++++++++++++-------- Lib/heapq.py | 14 +++++++++++++- Modules/_heapqmodule.c | 12 +++++++++++- 4 files changed, 49 insertions(+), 10 deletions(-) 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..8c043cc887b595 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 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\ From 5ff60b3f13af2114730a03ab97ff2547c94c2a4f Mon Sep 17 00:00:00 2001 From: kunwar-vikrant Date: Thu, 19 Mar 2026 20:37:36 +0530 Subject: [PATCH 2/3] Add news entry for gh-110067 docs improvements --- .../2026-03-19-00-00-01.gh-issue-110067.RZ_g-H9w.rst | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Misc/NEWS.d/next/Documentation/2026-03-19-00-00-01.gh-issue-110067.RZ_g-H9w.rst diff --git a/Misc/NEWS.d/next/Documentation/2026-03-19-00-00-01.gh-issue-110067.RZ_g-H9w.rst b/Misc/NEWS.d/next/Documentation/2026-03-19-00-00-01.gh-issue-110067.RZ_g-H9w.rst new file mode 100644 index 00000000000000..1d49b7c83bc958 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2026-03-19-00-00-01.gh-issue-110067.RZ_g-H9w.rst @@ -0,0 +1,2 @@ +Add max-heap usage examples to :mod:`heapq` module docstrings, a descending +heapsort example to the docs, and expand the What's New in 3.14 entry. From 134d0c3ad59fe5ea317db816f2fa53ccf2a05147 Mon Sep 17 00:00:00 2001 From: kunwar-vikrant Date: Thu, 19 Mar 2026 21:29:20 +0530 Subject: [PATCH 3/3] Address review: add Petr Viktorin to attribution, remove docs news entry --- Doc/whatsnew/3.14.rst | 2 +- .../2026-03-19-00-00-01.gh-issue-110067.RZ_g-H9w.rst | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) delete mode 100644 Misc/NEWS.d/next/Documentation/2026-03-19-00-00-01.gh-issue-110067.RZ_g-H9w.rst diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst index 8c043cc887b595..dc784a04719296 100644 --- a/Doc/whatsnew/3.14.rst +++ b/Doc/whatsnew/3.14.rst @@ -1399,7 +1399,7 @@ heapq * :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 in :gh:`110067`.) + (Contributed by Stan Ulbrych and Petr Viktorin in :gh:`110067`.) hmac diff --git a/Misc/NEWS.d/next/Documentation/2026-03-19-00-00-01.gh-issue-110067.RZ_g-H9w.rst b/Misc/NEWS.d/next/Documentation/2026-03-19-00-00-01.gh-issue-110067.RZ_g-H9w.rst deleted file mode 100644 index 1d49b7c83bc958..00000000000000 --- a/Misc/NEWS.d/next/Documentation/2026-03-19-00-00-01.gh-issue-110067.RZ_g-H9w.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add max-heap usage examples to :mod:`heapq` module docstrings, a descending -heapsort example to the docs, and expand the What's New in 3.14 entry.