_heapqmodule.c 21.5 KB
Newer Older
1
/* Drop in replacement for heapq.py
2 3 4

C implementation derived directly from heapq.py in Py2.3
which was written by Kevin O'Connor, augmented by Tim Peters,
5
annotated by François Pinard, and converted to C by Raymond Hettinger.
6 7 8 9 10

*/

#include "Python.h"

11 12 13 14 15 16 17
#include "clinic/_heapqmodule.c.h"

/*[clinic input]
module _heapq
[clinic start generated code]*/
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=d7cca0a2e4c0ceb3]*/

18
static int
19
siftdown(PyListObject *heap, Py_ssize_t startpos, Py_ssize_t pos)
20
{
21
    PyObject *newitem, *parent, **arr;
22
    Py_ssize_t parentpos, size;
23 24 25
    int cmp;

    assert(PyList_Check(heap));
26 27
    size = PyList_GET_SIZE(heap);
    if (pos >= size) {
28 29 30 31 32 33
        PyErr_SetString(PyExc_IndexError, "index out of range");
        return -1;
    }

    /* Follow the path to the root, moving parents down until finding
       a place newitem fits. */
34 35
    arr = _PyList_ITEMS(heap);
    newitem = arr[pos];
36
    while (pos > startpos) {
37
        parentpos = (pos - 1) >> 1;
38
        parent = arr[parentpos];
Raymond Hettinger's avatar
Raymond Hettinger committed
39
        cmp = PyObject_RichCompareBool(newitem, parent, Py_LT);
40
        if (cmp < 0)
41
            return -1;
42 43 44 45 46
        if (size != PyList_GET_SIZE(heap)) {
            PyErr_SetString(PyExc_RuntimeError,
                            "list changed size during iteration");
            return -1;
        }
47 48
        if (cmp == 0)
            break;
49 50 51 52 53
        arr = _PyList_ITEMS(heap);
        parent = arr[parentpos];
        newitem = arr[pos];
        arr[parentpos] = newitem;
        arr[pos] = parent;
54 55 56
        pos = parentpos;
    }
    return 0;
57 58 59
}

static int
60
siftup(PyListObject *heap, Py_ssize_t pos)
61
{
62
    Py_ssize_t startpos, endpos, childpos, limit;
63
    PyObject *tmp1, *tmp2, **arr;
64 65 66
    int cmp;

    assert(PyList_Check(heap));
67
    endpos = PyList_GET_SIZE(heap);
68 69 70 71 72 73 74
    startpos = pos;
    if (pos >= endpos) {
        PyErr_SetString(PyExc_IndexError, "index out of range");
        return -1;
    }

    /* Bubble up the smaller child until hitting a leaf. */
75
    arr = _PyList_ITEMS(heap);
76
    limit = endpos >> 1;         /* smallest pos that has no child */
77
    while (pos < limit) {
78
        /* Set childpos to index of smaller child.   */
79
        childpos = 2*pos + 1;    /* leftmost child position  */
80
        if (childpos + 1 < endpos) {
Raymond Hettinger's avatar
Raymond Hettinger committed
81
            cmp = PyObject_RichCompareBool(
82 83
                arr[childpos],
                arr[childpos + 1],
Raymond Hettinger's avatar
Raymond Hettinger committed
84
                Py_LT);
85
            if (cmp < 0)
86
                return -1;
87
            childpos += ((unsigned)cmp ^ 1);   /* increment when cmp==0 */
88
            arr = _PyList_ITEMS(heap);         /* arr may have changed */
89 90 91 92 93
            if (endpos != PyList_GET_SIZE(heap)) {
                PyErr_SetString(PyExc_RuntimeError,
                                "list changed size during iteration");
                return -1;
            }
94
        }
95
        /* Move the smaller child up. */
96 97 98 99
        tmp1 = arr[childpos];
        tmp2 = arr[pos];
        arr[childpos] = tmp2;
        arr[pos] = tmp1;
100 101
        pos = childpos;
    }
102
    /* Bubble it up to its final resting place (by sifting its parents down). */
103
    return siftdown(heap, startpos, pos);
104 105
}

106 107
/*[clinic input]
_heapq.heappush
108

109 110 111
    heap: object
    item: object
    /
112

113 114 115 116 117 118 119
Push item onto heap, maintaining the heap invariant.
[clinic start generated code]*/

static PyObject *
_heapq_heappush_impl(PyObject *module, PyObject *heap, PyObject *item)
/*[clinic end generated code: output=912c094f47663935 input=7913545cb5118842]*/
{
120 121 122 123
    if (!PyList_Check(heap)) {
        PyErr_SetString(PyExc_TypeError, "heap argument must be a list");
        return NULL;
    }
124

125
    if (PyList_Append(heap, item))
126
        return NULL;
127

128
    if (siftdown((PyListObject *)heap, 0, PyList_GET_SIZE(heap)-1))
129
        return NULL;
130
    Py_RETURN_NONE;
131 132 133
}

static PyObject *
134
heappop_internal(PyObject *heap, int siftup_func(PyListObject *, Py_ssize_t))
135
{
136 137 138 139 140 141 142 143
    PyObject *lastelt, *returnitem;
    Py_ssize_t n;

    if (!PyList_Check(heap)) {
        PyErr_SetString(PyExc_TypeError, "heap argument must be a list");
        return NULL;
    }

144
    /* raises IndexError if the heap is empty */
145 146 147 148 149 150 151 152
    n = PyList_GET_SIZE(heap);
    if (n == 0) {
        PyErr_SetString(PyExc_IndexError, "index out of range");
        return NULL;
    }

    lastelt = PyList_GET_ITEM(heap, n-1) ;
    Py_INCREF(lastelt);
153
    if (PyList_SetSlice(heap, n-1, n, NULL)) {
154 155 156
        Py_DECREF(lastelt);
        return NULL;
    }
157 158 159 160 161 162
    n--;

    if (!n)
        return lastelt;
    returnitem = PyList_GET_ITEM(heap, 0);
    PyList_SET_ITEM(heap, 0, lastelt);
163
    if (siftup_func((PyListObject *)heap, 0)) {
164 165 166 167
        Py_DECREF(returnitem);
        return NULL;
    }
    return returnitem;
168 169
}

170 171 172 173 174 175 176 177 178
/*[clinic input]
_heapq.heappop

    heap: object
    /

Pop the smallest item off the heap, maintaining the heap invariant.
[clinic start generated code]*/

179
static PyObject *
180 181
_heapq_heappop(PyObject *module, PyObject *heap)
/*[clinic end generated code: output=e1bbbc9866bce179 input=9bd36317b806033d]*/
182 183 184 185
{
    return heappop_internal(heap, siftup);
}

186
static PyObject *
187
heapreplace_internal(PyObject *heap, PyObject *item, int siftup_func(PyListObject *, Py_ssize_t))
188
{
189
    PyObject *returnitem;
190 191 192 193 194 195

    if (!PyList_Check(heap)) {
        PyErr_SetString(PyExc_TypeError, "heap argument must be a list");
        return NULL;
    }

196
    if (PyList_GET_SIZE(heap) == 0) {
197 198 199 200 201 202 203
        PyErr_SetString(PyExc_IndexError, "index out of range");
        return NULL;
    }

    returnitem = PyList_GET_ITEM(heap, 0);
    Py_INCREF(item);
    PyList_SET_ITEM(heap, 0, item);
204
    if (siftup_func((PyListObject *)heap, 0)) {
205 206 207 208
        Py_DECREF(returnitem);
        return NULL;
    }
    return returnitem;
209 210
}

211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229

/*[clinic input]
_heapq.heapreplace

    heap: object
    item: object
    /

Pop and return the current smallest value, and add the new item.

This is more efficient than heappop() followed by heappush(), and can be
more appropriate when using a fixed-size heap.  Note that the value
returned may be larger than item!  That constrains reasonable uses of
this routine unless written as part of a conditional replacement:

    if item > heap[0]:
        item = heapreplace(heap, item)
[clinic start generated code]*/

230
static PyObject *
231 232
_heapq_heapreplace_impl(PyObject *module, PyObject *heap, PyObject *item)
/*[clinic end generated code: output=82ea55be8fbe24b4 input=e57ae8f4ecfc88e3]*/
233
{
234
    return heapreplace_internal(heap, item, siftup);
235 236
}

237 238 239 240 241 242 243 244 245 246 247 248
/*[clinic input]
_heapq.heappushpop

    heap: object
    item: object
    /

Push item on the heap, then pop and return the smallest item from the heap.

The combined action runs more efficiently than heappush() followed by
a separate call to heappop().
[clinic start generated code]*/
249

Christian Heimes's avatar
Christian Heimes committed
250
static PyObject *
251 252
_heapq_heappushpop_impl(PyObject *module, PyObject *heap, PyObject *item)
/*[clinic end generated code: output=67231dc98ed5774f input=eb48c90ba77b2214]*/
Christian Heimes's avatar
Christian Heimes committed
253
{
254
    PyObject *returnitem;
255 256 257 258 259 260 261
    int cmp;

    if (!PyList_Check(heap)) {
        PyErr_SetString(PyExc_TypeError, "heap argument must be a list");
        return NULL;
    }

262
    if (PyList_GET_SIZE(heap) == 0) {
263 264 265 266
        Py_INCREF(item);
        return item;
    }

Raymond Hettinger's avatar
Raymond Hettinger committed
267
    cmp = PyObject_RichCompareBool(PyList_GET_ITEM(heap, 0), item, Py_LT);
268
    if (cmp < 0)
269 270 271 272 273 274
        return NULL;
    if (cmp == 0) {
        Py_INCREF(item);
        return item;
    }

275 276 277 278 279
    if (PyList_GET_SIZE(heap) == 0) {
        PyErr_SetString(PyExc_IndexError, "index out of range");
        return NULL;
    }

280 281 282
    returnitem = PyList_GET_ITEM(heap, 0);
    Py_INCREF(item);
    PyList_SET_ITEM(heap, 0, item);
283
    if (siftup((PyListObject *)heap, 0)) {
284 285 286 287
        Py_DECREF(returnitem);
        return NULL;
    }
    return returnitem;
Christian Heimes's avatar
Christian Heimes committed
288 289
}

290 291 292 293 294 295 296
static Py_ssize_t
keep_top_bit(Py_ssize_t n)
{
    int i = 0;

    while (n > 1) {
        n >>= 1;
297
        i++;
298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354
    }
    return n << i;
}

/* Cache friendly version of heapify()
   -----------------------------------

   Build-up a heap in O(n) time by performing siftup() operations
   on nodes whose children are already heaps.

   The simplest way is to sift the nodes in reverse order from
   n//2-1 to 0 inclusive.  The downside is that children may be
   out of cache by the time their parent is reached.

   A better way is to not wait for the children to go out of cache.
   Once a sibling pair of child nodes have been sifted, immediately
   sift their parent node (while the children are still in cache).

   Both ways build child heaps before their parents, so both ways
   do the exact same number of comparisons and produce exactly
   the same heap.  The only difference is that the traversal
   order is optimized for cache efficiency.
*/

static PyObject *
cache_friendly_heapify(PyObject *heap, int siftup_func(PyListObject *, Py_ssize_t))
{
    Py_ssize_t i, j, m, mhalf, leftmost;

    m = PyList_GET_SIZE(heap) >> 1;         /* index of first childless node */
    leftmost = keep_top_bit(m + 1) - 1;     /* leftmost node in row of m */
    mhalf = m >> 1;                         /* parent of first childless node */

    for (i = leftmost - 1 ; i >= mhalf ; i--) {
        j = i;
        while (1) {
            if (siftup_func((PyListObject *)heap, j))
                return NULL;
            if (!(j & 1))
                break;
            j >>= 1;
        }
    }

    for (i = m - 1 ; i >= leftmost ; i--) {
        j = i;
        while (1) {
            if (siftup_func((PyListObject *)heap, j))
                return NULL;
            if (!(j & 1))
                break;
            j >>= 1;
        }
    }
    Py_RETURN_NONE;
}

355
static PyObject *
356
heapify_internal(PyObject *heap, int siftup_func(PyListObject *, Py_ssize_t))
357
{
358 359 360 361 362 363 364
    Py_ssize_t i, n;

    if (!PyList_Check(heap)) {
        PyErr_SetString(PyExc_TypeError, "heap argument must be a list");
        return NULL;
    }

365 366 367 368
    /* For heaps likely to be bigger than L1 cache, we use the cache
       friendly heapify function.  For smaller heaps that fit entirely
       in cache, we prefer the simpler algorithm with less branching.
    */
369
    n = PyList_GET_SIZE(heap);
370
    if (n > 2500)
371 372
        return cache_friendly_heapify(heap, siftup_func);

373 374 375 376 377 378 379
    /* 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.
    */
380
    for (i = (n >> 1) - 1 ; i >= 0 ; i--)
381
        if (siftup_func((PyListObject *)heap, i))
382
            return NULL;
383 384 385
    Py_RETURN_NONE;
}

386 387 388 389 390 391 392 393 394
/*[clinic input]
_heapq.heapify

    heap: object
    /

Transform list into a heap, in-place, in O(len(heap)) time.
[clinic start generated code]*/

395
static PyObject *
396 397
_heapq_heapify(PyObject *module, PyObject *heap)
/*[clinic end generated code: output=11483f23627c4616 input=872c87504b8de970]*/
398 399
{
    return heapify_internal(heap, siftup);
400 401
}

402
static int
403
siftdown_max(PyListObject *heap, Py_ssize_t startpos, Py_ssize_t pos)
404
{
405
    PyObject *newitem, *parent, **arr;
406
    Py_ssize_t parentpos, size;
407 408 409
    int cmp;

    assert(PyList_Check(heap));
410 411
    size = PyList_GET_SIZE(heap);
    if (pos >= size) {
412 413 414 415 416 417
        PyErr_SetString(PyExc_IndexError, "index out of range");
        return -1;
    }

    /* Follow the path to the root, moving parents down until finding
       a place newitem fits. */
418 419
    arr = _PyList_ITEMS(heap);
    newitem = arr[pos];
420
    while (pos > startpos) {
421
        parentpos = (pos - 1) >> 1;
422
        parent = arr[parentpos];
Raymond Hettinger's avatar
Raymond Hettinger committed
423
        cmp = PyObject_RichCompareBool(parent, newitem, Py_LT);
424
        if (cmp < 0)
425
            return -1;
426 427 428 429 430
        if (size != PyList_GET_SIZE(heap)) {
            PyErr_SetString(PyExc_RuntimeError,
                            "list changed size during iteration");
            return -1;
        }
431 432
        if (cmp == 0)
            break;
433 434 435 436 437
        arr = _PyList_ITEMS(heap);
        parent = arr[parentpos];
        newitem = arr[pos];
        arr[parentpos] = newitem;
        arr[pos] = parent;
438 439 440
        pos = parentpos;
    }
    return 0;
441 442 443
}

static int
444
siftup_max(PyListObject *heap, Py_ssize_t pos)
445
{
446
    Py_ssize_t startpos, endpos, childpos, limit;
447
    PyObject *tmp1, *tmp2, **arr;
448 449 450 451 452 453 454 455 456 457 458
    int cmp;

    assert(PyList_Check(heap));
    endpos = PyList_GET_SIZE(heap);
    startpos = pos;
    if (pos >= endpos) {
        PyErr_SetString(PyExc_IndexError, "index out of range");
        return -1;
    }

    /* Bubble up the smaller child until hitting a leaf. */
459
    arr = _PyList_ITEMS(heap);
460
    limit = endpos >> 1;         /* smallest pos that has no child */
461
    while (pos < limit) {
462
        /* Set childpos to index of smaller child.   */
463
        childpos = 2*pos + 1;    /* leftmost child position  */
464
        if (childpos + 1 < endpos) {
Raymond Hettinger's avatar
Raymond Hettinger committed
465
            cmp = PyObject_RichCompareBool(
466 467
                arr[childpos + 1],
                arr[childpos],
Raymond Hettinger's avatar
Raymond Hettinger committed
468
                Py_LT);
469
            if (cmp < 0)
470
                return -1;
471
            childpos += ((unsigned)cmp ^ 1);   /* increment when cmp==0 */
472
            arr = _PyList_ITEMS(heap);         /* arr may have changed */
473 474 475 476 477
            if (endpos != PyList_GET_SIZE(heap)) {
                PyErr_SetString(PyExc_RuntimeError,
                                "list changed size during iteration");
                return -1;
            }
478 479
        }
        /* Move the smaller child up. */
480 481 482 483
        tmp1 = arr[childpos];
        tmp2 = arr[pos];
        arr[childpos] = tmp2;
        arr[pos] = tmp1;
484 485
        pos = childpos;
    }
486
    /* Bubble it up to its final resting place (by sifting its parents down). */
487
    return siftdown_max(heap, startpos, pos);
488 489
}

490 491 492 493 494 495 496 497 498 499

/*[clinic input]
_heapq._heappop_max

    heap: object
    /

Maxheap variant of heappop.
[clinic start generated code]*/

500
static PyObject *
501 502
_heapq__heappop_max(PyObject *module, PyObject *heap)
/*[clinic end generated code: output=acd30acf6384b13c input=62ede3ba9117f541]*/
503
{
504 505
    return heappop_internal(heap, siftup_max);
}
506

507 508 509 510 511 512 513 514 515
/*[clinic input]
_heapq._heapreplace_max

    heap: object
    item: object
    /

Maxheap variant of heapreplace.
[clinic start generated code]*/
516

517
static PyObject *
518 519 520
_heapq__heapreplace_max_impl(PyObject *module, PyObject *heap,
                             PyObject *item)
/*[clinic end generated code: output=8ad7545e4a5e8adb input=6d8f25131e0f0e5f]*/
521
{
522
    return heapreplace_internal(heap, item, siftup_max);
523
}
524

525 526 527 528 529 530 531 532
/*[clinic input]
_heapq._heapify_max

    heap: object
    /

Maxheap variant of heapify.
[clinic start generated code]*/
533

534
static PyObject *
535 536
_heapq__heapify_max(PyObject *module, PyObject *heap)
/*[clinic end generated code: output=1c6bb6b60d6a2133 input=cdfcc6835b14110d]*/
537 538
{
    return heapify_internal(heap, siftup_max);
539 540 541
}


542
static PyMethodDef heapq_methods[] = {
543 544 545 546 547 548 549 550 551
    _HEAPQ_HEAPPUSH_METHODDEF
    _HEAPQ_HEAPPUSHPOP_METHODDEF
    _HEAPQ_HEAPPOP_METHODDEF
    _HEAPQ_HEAPREPLACE_METHODDEF
    _HEAPQ_HEAPIFY_METHODDEF
    _HEAPQ__HEAPPOP_MAX_METHODDEF
    _HEAPQ__HEAPIFY_MAX_METHODDEF
    _HEAPQ__HEAPREPLACE_MAX_METHODDEF
    {NULL, NULL}           /* sentinel */
552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587
};

PyDoc_STRVAR(module_doc,
"Heap queue algorithm (a.k.a. priority queue).\n\
\n\
Heaps are arrays for which a[k] <= a[2*k+1] and a[k] <= a[2*k+2] for\n\
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\
\n\
heap = []            # creates an empty heap\n\
heappush(heap, item) # pushes a new item on the heap\n\
item = heappop(heap) # pops the smallest item from the heap\n\
item = heap[0]       # smallest item on the heap without popping it\n\
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\
Our API differs from textbook heap algorithms as follows:\n\
\n\
- We use 0-based indexing.  This makes the relationship between the\n\
  index for a node and the indexes for its children slightly less\n\
  obvious, but is more suitable since Python uses 0-based indexing.\n\
\n\
- Our heappop() method returns the smallest item, not the largest.\n\
\n\
These two make it possible to view the heap as a regular Python list\n\
without surprises: heap[0] is the smallest item, and heap.sort()\n\
maintains the heap invariant!\n");


PyDoc_STRVAR(__about__,
"Heap queues\n\
\n\
588
[explanation by Fran\xc3\xa7ois Pinard]\n\
589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609
\n\
Heaps are arrays for which a[k] <= a[2*k+1] and a[k] <= a[2*k+2] for\n\
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\
The strange invariant above is meant to be an efficient memory\n\
representation for a tournament.  The numbers below are `k', not a[k]:\n\
\n\
                                   0\n\
\n\
                  1                                 2\n\
\n\
          3               4                5               6\n\
\n\
      7       8       9       10      11      12      13      14\n\
\n\
    15 16   17 18   19 20   21 22   23 24   25 26   27 28   29 30\n\
\n\
\n\
In the tree above, each cell `k' is topping `2*k+1' and `2*k+2'.  In\n\
610
a usual binary tournament we see in sports, each cell is the winner\n\
611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678
over the two cells it tops, and we can trace the winner down the tree\n\
to see all opponents s/he had.  However, in many computer applications\n\
of such tournaments, we do not need to trace the history of a winner.\n\
To be more memory efficient, when a winner is promoted, we try to\n\
replace it by something else at a lower level, and the rule becomes\n\
that a cell and the two cells it tops contain three different items,\n\
but the top cell \"wins\" over the two topped cells.\n"
"\n\
If this heap invariant is protected at all time, index 0 is clearly\n\
the overall winner.  The simplest algorithmic way to remove it and\n\
find the \"next\" winner is to move some loser (let's say cell 30 in the\n\
diagram above) into the 0 position, and then percolate this new 0 down\n\
the tree, exchanging values, until the invariant is re-established.\n\
This is clearly logarithmic on the total number of items in the tree.\n\
By iterating over all items, you get an O(n ln n) sort.\n"
"\n\
A nice feature of this sort is that you can efficiently insert new\n\
items while the sort is going on, provided that the inserted items are\n\
not \"better\" than the last 0'th element you extracted.  This is\n\
especially useful in simulation contexts, where the tree holds all\n\
incoming events, and the \"win\" condition means the smallest scheduled\n\
time.  When an event schedule other events for execution, they are\n\
scheduled into the future, so they can easily go into the heap.  So, a\n\
heap is a good structure for implementing schedulers (this is what I\n\
used for my MIDI sequencer :-).\n"
"\n\
Various structures for implementing schedulers have been extensively\n\
studied, and heaps are good for this, as they are reasonably speedy,\n\
the speed is almost constant, and the worst case is not much different\n\
than the average case.  However, there are other representations which\n\
are more efficient overall, yet the worst cases might be terrible.\n"
"\n\
Heaps are also very useful in big disk sorts.  You most probably all\n\
know that a big sort implies producing \"runs\" (which are pre-sorted\n\
sequences, which size is usually related to the amount of CPU memory),\n\
followed by a merging passes for these runs, which merging is often\n\
very cleverly organised[1].  It is very important that the initial\n\
sort produces the longest runs possible.  Tournaments are a good way\n\
to that.  If, using all the memory available to hold a tournament, you\n\
replace and percolate items that happen to fit the current run, you'll\n\
produce runs which are twice the size of the memory for random input,\n\
and much better for input fuzzily ordered.\n"
"\n\
Moreover, if you output the 0'th item on disk and get an input which\n\
may not fit in the current tournament (because the value \"wins\" over\n\
the last output value), it cannot fit in the heap, so the size of the\n\
heap decreases.  The freed memory could be cleverly reused immediately\n\
for progressively building a second heap, which grows at exactly the\n\
same rate the first heap is melting.  When the first heap completely\n\
vanishes, you switch heaps and start a new run.  Clever and quite\n\
effective!\n\
\n\
In a word, heaps are useful memory structures to know.  I use them in\n\
a few applications, and I think it is good to keep a `heap' module\n\
around. :-)\n"
"\n\
--------------------\n\
[1] The disk balancing algorithms which are current, nowadays, are\n\
more annoying than clever, and this is a consequence of the seeking\n\
capabilities of the disks.  On devices which cannot seek, like big\n\
tape drives, the story was quite different, and one had to be very\n\
clever to ensure (far in advance) that each tape movement will be the\n\
most effective possible (that is, will best participate at\n\
\"progressing\" the merge).  Some tapes were even able to read\n\
backwards, and this was also used to avoid the rewinding time.\n\
Believe me, real good tape sorts were quite spectacular to watch!\n\
From all times, sorting has always been a Great Art! :-)\n");

679 680

static struct PyModuleDef _heapqmodule = {
681 682 683 684 685 686 687 688 689
    PyModuleDef_HEAD_INIT,
    "_heapq",
    module_doc,
    -1,
    heapq_methods,
    NULL,
    NULL,
    NULL,
    NULL
690 691
};

692
PyMODINIT_FUNC
693
PyInit__heapq(void)
694
{
695 696 697 698 699 700 701 702
    PyObject *m, *about;

    m = PyModule_Create(&_heapqmodule);
    if (m == NULL)
        return NULL;
    about = PyUnicode_DecodeUTF8(__about__, strlen(__about__), NULL);
    PyModule_AddObject(m, "__about__", about);
    return m;
703 704
}