Skip to content

Commit 1159b98

Browse files
committed
BST select() done and tested :)
1 parent 51f36cb commit 1159b98

File tree

2 files changed

+77
-0
lines changed

2 files changed

+77
-0
lines changed

pydatastructs/trees/_backend/cpp/BinarySearchTree.hpp

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -588,6 +588,77 @@ static PyObject* BinarySearchTree_rank(BinarySearchTree* self, PyObject* args) {
588588
return PyLong_FromLong(r);
589589
}
590590

591+
static PyObject* BinarySearchTree_select(BinarySearchTree* self, PyObject* args) {
592+
long i = PyLong_AsLong(PyObject_GetItem(args, PyZero));
593+
i = i - 1;
594+
if (i < 0) {
595+
PyErr_SetString(PyExc_ValueError, "Expected a positive integer");
596+
return NULL;
597+
}
598+
BinaryTree* bt = self->binary_tree;
599+
if (i >= bt->tree->_num) {
600+
PyErr_SetString(PyExc_ValueError, "Integer passed to select() is greater than the size of the tree.");
601+
return NULL;
602+
}
603+
PyObject* walk = bt->root_idx;
604+
while (walk != Py_None) {
605+
long l = BinarySearchTree_left_size(self, reinterpret_cast<TreeNode*>(bt->tree->_one_dimensional_array->_data[PyLong_AsLong(walk)]));
606+
if (i == l) {
607+
return bt->tree->_one_dimensional_array->_data[PyLong_AsLong(walk)];
608+
}
609+
PyObject* left_walk = reinterpret_cast<TreeNode*>(bt->tree->_one_dimensional_array->_data[PyLong_AsLong(walk)])->left;
610+
PyObject* right_walk = reinterpret_cast<TreeNode*>(bt->tree->_one_dimensional_array->_data[PyLong_AsLong(walk)])->right;
611+
if (left_walk == Py_None && right_walk==Py_None) {
612+
PyErr_SetString(PyExc_IndexError, "The traversal is terminated due to no child nodes ahead.");
613+
return NULL;
614+
}
615+
if (i < l) {
616+
if (!PyCallable_Check(bt->comparator)) {
617+
PyErr_SetString(PyExc_ValueError, "comparator should be callable");
618+
return NULL;
619+
}
620+
PyObject* arguments = Py_BuildValue("OO", reinterpret_cast<TreeNode*>(bt->tree->_one_dimensional_array->_data[PyLong_AsLong(left_walk)])->key, reinterpret_cast<TreeNode*>(bt->tree->_one_dimensional_array->_data[PyLong_AsLong(walk)])->key);
621+
PyObject* cres = PyObject_CallObject(bt->comparator, arguments);
622+
Py_DECREF(arguments);
623+
if (!PyLong_Check(cres)) {
624+
PyErr_SetString(PyExc_TypeError, "bad return type from comparator");
625+
return NULL;
626+
}
627+
long long comp = PyLong_AsLongLong(cres);
628+
629+
if (left_walk != Py_None && comp) {
630+
walk = left_walk;
631+
}
632+
else {
633+
walk = right_walk;
634+
}
635+
}
636+
else {
637+
if (!PyCallable_Check(bt->comparator)) {
638+
PyErr_SetString(PyExc_ValueError, "comparator should be callable");
639+
return NULL;
640+
}
641+
PyObject* arguments = Py_BuildValue("OO", reinterpret_cast<TreeNode*>(bt->tree->_one_dimensional_array->_data[PyLong_AsLong(right_walk)])->key, reinterpret_cast<TreeNode*>(bt->tree->_one_dimensional_array->_data[PyLong_AsLong(walk)])->key);
642+
PyObject* cres = PyObject_CallObject(bt->comparator, arguments);
643+
Py_DECREF(arguments);
644+
if (!PyLong_Check(cres)) {
645+
PyErr_SetString(PyExc_TypeError, "bad return type from comparator");
646+
return NULL;
647+
}
648+
long long comp = PyLong_AsLongLong(cres);
649+
650+
if (right_walk != Py_None && (!comp)) {
651+
walk = right_walk;
652+
}
653+
else {
654+
walk = left_walk;
655+
}
656+
i = i - (l + 1);
657+
}
658+
}
659+
Py_RETURN_NONE; // This is a dummy return
660+
}
661+
591662
static struct PyMethodDef BinarySearchTree_PyMethodDef[] = {
592663
{"insert", (PyCFunction) BinarySearchTree_insert, METH_VARARGS | METH_KEYWORDS, NULL},
593664
{"delete", (PyCFunction) BinarySearchTree_delete, METH_VARARGS | METH_KEYWORDS, NULL},
@@ -599,6 +670,7 @@ static struct PyMethodDef BinarySearchTree_PyMethodDef[] = {
599670
{"_lca_2", (PyCFunction) BinarySearchTree__lca_2, METH_VARARGS, NULL},
600671
{"lowest_common_ancestor", (PyCFunction) BinarySearchTree_lowest_common_ancestor, METH_VARARGS, NULL},
601672
{"rank", (PyCFunction) BinarySearchTree_rank, METH_VARARGS, NULL},
673+
{"select", (PyCFunction) BinarySearchTree_select, METH_VARARGS, NULL},
602674
{NULL}
603675
};
604676

pydatastructs/trees/tests/test_binary_trees.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,11 @@ def test_cpp_BST2():
156156
rank_list = [2, 2, 4, 4, 5, 4, 5, 3, 2, 3, 2, 1, 3, 4, 5]
157157
for i,node in enumerate(nodes):
158158
assert bl2.rank(node) == rank_list[i]
159+
assert bl2.rank(200) is None
160+
161+
select_list = [10, 50, 55, 90, 100]
162+
for i in range(5):
163+
assert bl2.select(i+1).key == select_list[i]
159164

160165
b3 = BST(backend=Backend.CPP)
161166
# b3 = BST()

0 commit comments

Comments
 (0)