summaryrefslogtreecommitdiffstats
path: root/Modules/_heapqmodule.c
diff options
context:
space:
mode:
authorRaymond Hettinger <python@rcn.com>2014-05-11 21:21:23 (GMT)
committerRaymond Hettinger <python@rcn.com>2014-05-11 21:21:23 (GMT)
commit234fb2d503cd8f8bae56eb7fa4d0a88cd1b7c03a (patch)
treef162da1b8eb602ca7e416e648c3ae24ee0674794 /Modules/_heapqmodule.c
parent3a17e2175589e6f4b5945dc661308167347dc22f (diff)
downloadcpython-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.c92
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 */
};