diff options
author | Raymond Hettinger <python@rcn.com> | 2014-05-11 21:21:23 (GMT) |
---|---|---|
committer | Raymond Hettinger <python@rcn.com> | 2014-05-11 21:21:23 (GMT) |
commit | 234fb2d503cd8f8bae56eb7fa4d0a88cd1b7c03a (patch) | |
tree | f162da1b8eb602ca7e416e648c3ae24ee0674794 /Modules/_heapqmodule.c | |
parent | 3a17e2175589e6f4b5945dc661308167347dc22f (diff) | |
download | cpython-234fb2d503cd8f8bae56eb7fa4d0a88cd1b7c03a.zip cpython-234fb2d503cd8f8bae56eb7fa4d0a88cd1b7c03a.tar.gz cpython-234fb2d503cd8f8bae56eb7fa4d0a88cd1b7c03a.tar.bz2 |
Issue 21424: Apply the nlargest() optimizations to nsmallest() as well.
Diffstat (limited to 'Modules/_heapqmodule.c')
-rw-r--r-- | Modules/_heapqmodule.c | 92 |
1 files changed, 19 insertions, 73 deletions
diff --git a/Modules/_heapqmodule.c b/Modules/_heapqmodule.c index 964f511..ad190df 100644 --- a/Modules/_heapqmodule.c +++ b/Modules/_heapqmodule.c @@ -354,88 +354,34 @@ _siftupmax(PyListObject *heap, Py_ssize_t pos) } static PyObject * -nsmallest(PyObject *self, PyObject *args) +_heapreplace_max(PyObject *self, PyObject *args) { - PyObject *heap=NULL, *elem, *iterable, *los, *it, *oldelem; - Py_ssize_t i, n; - int cmp; + PyObject *heap, *item, *returnitem; - if (!PyArg_ParseTuple(args, "nO:nsmallest", &n, &iterable)) + if (!PyArg_UnpackTuple(args, "_heapreplace_max", 2, 2, &heap, &item)) return NULL; - it = PyObject_GetIter(iterable); - if (it == NULL) + if (!PyList_Check(heap)) { + PyErr_SetString(PyExc_TypeError, "heap argument must be a list"); return NULL; - - heap = PyList_New(0); - if (heap == NULL) - goto fail; - - for (i=0 ; i<n ; i++ ){ - elem = PyIter_Next(it); - if (elem == NULL) { - if (PyErr_Occurred()) - goto fail; - else - goto sortit; - } - if (PyList_Append(heap, elem) == -1) { - Py_DECREF(elem); - goto fail; - } - Py_DECREF(elem); } - n = PyList_GET_SIZE(heap); - if (n == 0) - goto sortit; - - for (i=n/2-1 ; i>=0 ; i--) - if(_siftupmax((PyListObject *)heap, i) == -1) - goto fail; - - los = PyList_GET_ITEM(heap, 0); - while (1) { - elem = PyIter_Next(it); - if (elem == NULL) { - if (PyErr_Occurred()) - goto fail; - else - goto sortit; - } - cmp = PyObject_RichCompareBool(elem, los, Py_LT); - if (cmp == -1) { - Py_DECREF(elem); - goto fail; - } - if (cmp == 0) { - Py_DECREF(elem); - continue; - } - oldelem = PyList_GET_ITEM(heap, 0); - PyList_SET_ITEM(heap, 0, elem); - Py_DECREF(oldelem); - if (_siftupmax((PyListObject *)heap, 0) == -1) - goto fail; - los = PyList_GET_ITEM(heap, 0); + if (PyList_GET_SIZE(heap) < 1) { + PyErr_SetString(PyExc_IndexError, "index out of range"); + return NULL; } -sortit: - if (PyList_Sort(heap) == -1) - goto fail; - Py_DECREF(it); - return heap; - -fail: - Py_DECREF(it); - Py_XDECREF(heap); - return NULL; + returnitem = PyList_GET_ITEM(heap, 0); + Py_INCREF(item); + PyList_SET_ITEM(heap, 0, item); + if (_siftupmax((PyListObject *)heap, 0) == -1) { + Py_DECREF(returnitem); + return NULL; + } + return returnitem; } -PyDoc_STRVAR(nsmallest_doc, -"Find the n smallest elements in a dataset.\n\ -\n\ -Equivalent to: sorted(iterable)[:n]\n"); +PyDoc_STRVAR(heapreplace_max_doc, "Maxheap variant of heapreplace"); static PyMethodDef heapq_methods[] = { {"heappush", (PyCFunction)heappush, @@ -448,8 +394,8 @@ static PyMethodDef heapq_methods[] = { METH_VARARGS, heapreplace_doc}, {"heapify", (PyCFunction)heapify, METH_O, heapify_doc}, - {"nsmallest", (PyCFunction)nsmallest, - METH_VARARGS, nsmallest_doc}, + {"_heapreplace_max",(PyCFunction)_heapreplace_max, + METH_VARARGS, heapreplace_max_doc}, {NULL, NULL} /* sentinel */ }; |