Skip to content

Commit f4fd94a

Browse files
Benedikt's requested changes
1 parent fc46707 commit f4fd94a

File tree

4 files changed

+41
-33
lines changed

4 files changed

+41
-33
lines changed

Doc/library/heapq.rst

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,10 @@
1616
This module provides an implementation of the heap queue algorithm, also known
1717
as the priority queue algorithm.
1818

19-
Heaps are binary trees for which every parent node has a value less than or
20-
equal to any of its children. We refer to this condition as the heap invariant.
19+
in-heaps (resp. max-heaps) are binary trees for which every parent node
20+
has a value less than (resp. greater than) or equal to any of its children.
21+
We refer to this condition as the heap invariant. Unless stated otherwise,
22+
*heaps* refer to min-heaps.
2123

2224
This implementation uses arrays for which
2325
``heap[k] <= heap[2*k+1]`` and ``heap[k] <= heap[2*k+2]`` for all *k*, counting
@@ -82,45 +84,45 @@ The following functions are provided:
8284
on the heap.
8385

8486

85-
For max heaps, the reverse of a heap, the following functions are provided:
87+
For max-heaps, the reverse of a heap, the following functions are provided:
8688

8789

8890
.. function:: heapify_max(x)
8991

90-
Transform list *x* into a max heap, in-place, in linear time.
92+
Transform list *x* into a max-heap, in-place, in linear time.
9193

9294
.. versionadded:: next
9395

9496

9597
.. function:: heappush_max(heap, item)
9698

97-
Push the value *item* onto the max *heap*, maintaining the heap invariant.
99+
Push the value *item* onto the max-*heap*, maintaining the heap invariant.
98100

99101
.. versionadded:: next
100102

101103

102104
.. function:: heappop_max(heap)
103105

104-
Pop and return the largest item from the max *heap*, maintaining the heap
105-
invariant. If the max heap is empty, :exc:`IndexError` is raised. To access the
106+
Pop and return the largest item from the max-*heap*, maintaining the heap
107+
invariant. If the max-heap is empty, :exc:`IndexError` is raised. To access the
106108
largest item without popping it, use ``heap[0]``.
107109

108110
.. versionadded:: next
109111

110112

111113
.. function:: heappushpop_max(heap, item)
112114

113-
Push *item* on the max heap, then pop and return the largest item from the max
114-
*heap*. The combined action runs more efficiently than :func:`heappush_max`
115+
Push *item* on the max-heap, then pop and return the largest item from *heap*.
116+
The combined action runs more efficiently than :func:`heappush_max`
115117
followed by a separate call to :func:`heappop_max`.
116118

117119
.. versionadded:: next
118120

119121

120122
.. function:: heapreplace_max(heap, item)
121123

122-
Pop and return the largest item from the max *heap*, and also push the new *item*.
123-
The max heap size doesn't change. If the max heap is empty, :exc:`IndexError` is raised.
124+
Pop and return the largest item from the max-heap *heap* and also push the new *item*.
125+
The max-heap size doesn't change. If the max-heap is empty, :exc:`IndexError` is raised.
124126

125127
This one step operation is more efficient than a :func:`heappop_max` followed by
126128
:func:`heappush_max` and can be more appropriate when using a fixed-size heap.

Lib/heapq.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -213,13 +213,6 @@ def heapify_max(x):
213213
for i in reversed(range(n//2)):
214214
_siftup_max(x, i)
215215

216-
# For backwards compadibility
217-
_heappop_max = heappop_max
218-
_heapreplace_max = heapreplace_max
219-
_heappush_max = heappush_max
220-
_heappushpop_max = heappushpop_max
221-
_heapify_max = heapify_max
222-
223216

224217
# 'heap' is a heap at all indices >= startpos, except possibly for pos. pos
225218
# is the index of a leaf with a possibly out-of-order value. Restore the
@@ -604,6 +597,12 @@ def nlargest(n, iterable, key=None):
604597
except ImportError:
605598
pass
606599

600+
# For backwards compatibility
601+
_heappop_max = heappop_max
602+
_heapreplace_max = heapreplace_max
603+
_heappush_max = heappush_max
604+
_heappushpop_max = heappushpop_max
605+
_heapify_max = heapify_max
607606

608607
if __name__ == "__main__":
609608

Lib/test/test_heapq.py

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
# _heapq.nlargest/nsmallest are saved in heapq._nlargest/_smallest when
1515
# _heapq is imported, so check them there
1616
func_names = ['heapify', 'heappop', 'heappush', 'heappushpop', 'heapreplace',
17-
'heappop_max', 'heapreplace_max', 'heapify_max', 'heappushpop_max',]
17+
'heappop_max', 'heapreplace_max', 'heapify_max', 'heappushpop_max']
1818

1919
class TestModules(TestCase):
2020
def test_py_functions(self):
@@ -96,10 +96,10 @@ def test_max_push_pop(self):
9696
# 2) Check that the invariant holds for a sorted array
9797
self.check_max_invariant(results)
9898

99-
self.assertRaises(TypeError, self.module.heappush, [])
99+
self.assertRaises(TypeError, self.module.heappush_max, [])
100100
try:
101-
self.assertRaises(TypeError, self.module.heappush, None, None)
102-
self.assertRaises(TypeError, self.module.heappop, None)
101+
self.assertRaises(TypeError, self.module.heappush_max, None, None)
102+
self.assertRaises(TypeError, self.module.heappop_max, None)
103103
except AttributeError:
104104
pass
105105

@@ -113,7 +113,7 @@ def check_invariant(self, heap):
113113
def check_max_invariant(self, heap):
114114
for pos in range(1, len(heap)):
115115
parentpos = (pos - 1) >> 1
116-
self.assertTrue(heap[parentpos] >= heap[pos])
116+
self.assertGreaterEqual(heap[parentpos], heap[pos])
117117

118118
def test_heapify(self):
119119
for size in list(range(30)) + [20000]:
@@ -129,7 +129,7 @@ def test_heapify_max(self):
129129
self.module.heapify_max(heap)
130130
self.check_max_invariant(heap)
131131

132-
self.assertRaises(TypeError, self.module.heapify, None)
132+
self.assertRaises(TypeError, self.module.heapify_max, None)
133133

134134
def test_naive_nbest(self):
135135
data = [random.randrange(2000) for i in range(1000)]
@@ -198,21 +198,21 @@ def test_heappushpop(self):
198198
def test_heappushpop_max(self):
199199
h = []
200200
x = self.module.heappushpop_max(h, 10)
201-
self.assertEqual((h, x), ([], 10))
201+
self.assertTupleEqual((h, x), ([], 10))
202202

203203
h = [10]
204204
x = self.module.heappushpop_max(h, 10.0)
205-
self.assertEqual((h, x), ([10], 10.0))
206-
self.assertEqual(type(h[0]), int)
207-
self.assertEqual(type(x), float)
205+
self.assertTupleEqual((h, x), ([10], 10.0))
206+
self.assertIsInstance(h[0], int)
207+
self.assertIsInstance(x, float)
208208

209209
h = [10]
210210
x = self.module.heappushpop_max(h, 11)
211-
self.assertEqual((h, x), ([11], 10))
211+
self.assertTupleEqual((h, x), ([11], 10))
212212

213213
h = [10]
214214
x = self.module.heappushpop_max(h, 9)
215-
self.assertEqual((h, x), ([10], 9))
215+
self.assertTupleEqual((h, x), ([10], 9))
216216

217217
def test_heappop_max(self):
218218
# heapop_max has an optimization for one-item lists which isn't

Modules/_heapqmodule.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -549,9 +549,11 @@ _heapq_heappushpop_max_impl(PyObject *module, PyObject *heap, PyObject *item)
549549
{
550550
PyObject *returnitem;
551551
int cmp;
552+
552553
if (PyList_GET_SIZE(heap) == 0) {
553554
return Py_NewRef(item);
554555
}
556+
555557
PyObject *top = PyList_GET_ITEM(heap, 0);
556558
Py_INCREF(top);
557559
cmp = PyObject_RichCompareBool(top, item, Py_LT);
@@ -562,14 +564,19 @@ _heapq_heappushpop_max_impl(PyObject *module, PyObject *heap, PyObject *item)
562564
if (cmp == 0) {
563565
return Py_NewRef(item);
564566
}
567+
568+
if (PyList_GET_SIZE(heap) == 0) {
569+
PyErr_SetString(PyExc_IndexError, "index out of range");
570+
return NULL;
571+
}
572+
565573
returnitem = PyList_GET_ITEM(heap, 0);
566574
PyList_SET_ITEM(heap, 0, Py_NewRef(item));
567-
568-
if (siftup_max((PyListObject *)heap, 0)) {
575+
if (siftup_max((PyListObject *)heap, 0) < 0) {
569576
Py_DECREF(returnitem);
570577
return NULL;
571578
}
572-
return Py_NewRef(returnitem);
579+
return returnitem;
573580
}
574581

575582
static PyMethodDef heapq_methods[] = {

0 commit comments

Comments
 (0)