added a priority heap
This commit is contained in:
parent
ceb350be14
commit
fb3b03b807
|
|
@ -0,0 +1,15 @@
|
|||
// DIR_TYPE "metalib" indicates we are building a shared library that
|
||||
// consists mostly of references to other shared libraries. Under
|
||||
// Windows, this directly produces a DLL (as opposed to the regular
|
||||
// src libraries, which don't produce anything but a pile of OBJ files
|
||||
// under Windows).
|
||||
|
||||
#define DIR_TYPE metalib
|
||||
#define BUILDING_DLL BUILDING_DIRECT
|
||||
|
||||
#begin metalib_target
|
||||
#define TARGET heapq
|
||||
|
||||
#define SOURCES heapq.c
|
||||
#end metalib_target
|
||||
|
||||
|
|
@ -0,0 +1,188 @@
|
|||
|
||||
/* Note: This module can probably go away when we upgrade to Python 2.4.
|
||||
Python 2.3 has a heapq implementation, but it is in Python. This is
|
||||
reported to be about 20x faster. In 2.4 they reimplemented heapq in C so
|
||||
it should be comparable to this. At this time though, Python 2.4 is
|
||||
still in alpha.
|
||||
*/
|
||||
|
||||
#include <Python.h>
|
||||
|
||||
/* Prototypes */
|
||||
static PyObject * heappush(PyObject *self, PyObject *args);
|
||||
static PyObject * heappop(PyObject *self, PyObject *args);
|
||||
static PyObject * heapreplace(PyObject *self, PyObject *args);
|
||||
static PyObject * heapify(PyObject *self, PyObject *args);
|
||||
static int _siftdown(PyObject *list, int startpos, int pos);
|
||||
static int _siftup(PyObject *list, int pos);
|
||||
|
||||
#ifdef _WIN32
|
||||
extern __declspec(dllexport) void initlibheapq(void);
|
||||
#else
|
||||
extern void initlibheapq();
|
||||
#endif
|
||||
|
||||
static PyObject *
|
||||
heappush(PyObject *self, PyObject *args) {
|
||||
int len;
|
||||
PyObject *list = NULL;
|
||||
PyObject *node = NULL;
|
||||
|
||||
if (!PyArg_ParseTuple(args,"O!O",&PyList_Type,&list,&node))
|
||||
return NULL;
|
||||
|
||||
len = PyList_Size(list);
|
||||
if (PyList_Append(list,node))
|
||||
return NULL;
|
||||
|
||||
if (_siftdown(list,0,len))
|
||||
return NULL;
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
heappop(PyObject *self, PyObject *args) {
|
||||
PyObject *list = NULL;
|
||||
PyObject *node = NULL;
|
||||
PyObject *returnNode = NULL;
|
||||
int len;
|
||||
|
||||
if (!PyArg_ParseTuple(args,"O!",&PyList_Type,&list))
|
||||
return NULL;
|
||||
|
||||
len = PyList_Size(list);
|
||||
if (len == 0) {
|
||||
/* Special-case most common failure cause */
|
||||
PyErr_SetString(PyExc_IndexError, "pop from empty list");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
node = PySequence_GetItem(list,-1);
|
||||
PySequence_DelItem(list,-1);
|
||||
|
||||
len -= 1;
|
||||
if (len > 0) {
|
||||
returnNode = PySequence_GetItem(list,0);
|
||||
PyList_SetItem(list,0,node);
|
||||
if (_siftup(list,0))
|
||||
return NULL;
|
||||
} else {
|
||||
returnNode = node;
|
||||
}
|
||||
|
||||
return returnNode;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
heapreplace(PyObject *self, PyObject *args) {
|
||||
PyObject *list = NULL;
|
||||
PyObject *node = NULL;
|
||||
PyObject *returnNode = NULL;
|
||||
int len;
|
||||
|
||||
if (!PyArg_ParseTuple(args,"O!O",&PyList_Type,&list,&node))
|
||||
return NULL;
|
||||
|
||||
len = PyList_Size(list);
|
||||
if (len == 0) {
|
||||
/* Special-case most common failure cause */
|
||||
PyErr_SetString(PyExc_IndexError, "replace on an empty list");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
returnNode = PySequence_GetItem(list,0);
|
||||
PySequence_SetItem(list,0,node);
|
||||
if (_siftup(list,0))
|
||||
return NULL;
|
||||
|
||||
return returnNode;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
heapify(PyObject *self, PyObject *args) {
|
||||
int n, i;
|
||||
PyObject *list;
|
||||
|
||||
if (!PyArg_ParseTuple(args,"O!",&PyList_Type,&list))
|
||||
return NULL;
|
||||
n = (PyList_Size(list)/2)-1;
|
||||
|
||||
for (i=n;i>=0;i--) {
|
||||
if (_siftup(list,i))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
static int
|
||||
_siftdown(PyObject *list, int startpos, int pos) {
|
||||
PyObject *newitem, *parent;
|
||||
int parentpos, cmp;
|
||||
|
||||
newitem = PySequence_GetItem(list,pos);
|
||||
while (pos > startpos) {
|
||||
parentpos = (pos - 1) >> 1;
|
||||
parent = PyList_GetItem(list,parentpos);
|
||||
|
||||
cmp = PyObject_RichCompareBool(parent,newitem,Py_LE);
|
||||
if (cmp > 0)
|
||||
break;
|
||||
else if (cmp < 0)
|
||||
return -1;
|
||||
Py_INCREF(parent);
|
||||
PyList_SetItem(list,pos,parent);
|
||||
pos = parentpos;
|
||||
}
|
||||
PyList_SetItem(list,pos,newitem);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
_siftup(PyObject *list, int pos) {
|
||||
PyObject *newitem, *right, *child;
|
||||
int endpos, rightpos, childpos;
|
||||
int startpos = pos;
|
||||
int cmp;
|
||||
|
||||
endpos = PyList_Size(list);
|
||||
newitem = PySequence_GetItem(list,pos);
|
||||
|
||||
childpos = (2*pos)+1;
|
||||
while (childpos < endpos) {
|
||||
rightpos = childpos + 1;
|
||||
child = PySequence_Fast_GET_ITEM(list,childpos);
|
||||
if (rightpos < endpos) {
|
||||
right = PySequence_Fast_GET_ITEM(list,rightpos);
|
||||
cmp = PyObject_RichCompareBool(right,child,Py_LE);
|
||||
if (cmp > 0)
|
||||
childpos = rightpos;
|
||||
else if (cmp < 0)
|
||||
return -1;
|
||||
}
|
||||
child = PySequence_GetItem(list,childpos);
|
||||
PyList_SetItem(list,pos,child);
|
||||
pos = childpos;
|
||||
childpos = (2*pos)+1;
|
||||
}
|
||||
PyList_SetItem(list,pos,newitem);
|
||||
|
||||
return _siftdown(list,startpos,pos);
|
||||
}
|
||||
|
||||
static PyMethodDef heapqcMethods[] = {
|
||||
{"heappush",heappush,METH_VARARGS},
|
||||
{"heappop",heappop,METH_VARARGS},
|
||||
{"heapreplace",heapreplace,METH_VARARGS},
|
||||
{"heapify",heapify,METH_VARARGS},
|
||||
{NULL, NULL} /* Sentinel */
|
||||
};
|
||||
|
||||
void initlibheapq(void) {
|
||||
(void) Py_InitModule("libheapq", heapqcMethods);
|
||||
};
|
||||
|
||||
|
||||
Loading…
Reference in New Issue