Skip to content

Commit

Permalink
BST Lowest Common Ancestor by lca1 done and tested
Browse files Browse the repository at this point in the history
  • Loading branch information
Kishan-Ved committed May 28, 2024
1 parent bda0dd1 commit 21c74f5
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 4 deletions.
56 changes: 56 additions & 0 deletions pydatastructs/trees/_backend/cpp/BinarySearchTree.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -428,13 +428,69 @@ static PyObject* BinarySearchTree__simple_path(BinarySearchTree* self, PyObject
return path;
}

static PyObject* BinarySearchTree__lca_1(BinarySearchTree* self, PyObject* args) {
long j = PyLong_AsLong(PyObject_GetItem(args, PyZero));
long k = PyLong_AsLong(PyObject_GetItem(args, PyOne));
BinaryTree* bt = self->binary_tree;
PyObject* root = bt->root_idx;
PyObject* path1 = BinarySearchTree__simple_path(self, Py_BuildValue("(OO)",PyLong_FromLong(j),root));
PyObject* path2 = BinarySearchTree__simple_path(self, Py_BuildValue("(OO)",PyLong_FromLong(k),root));
long n = PyLong_AsLong(PyLong_FromSsize_t(PyList_Size(path1)));
long m = PyLong_AsLong(PyLong_FromSsize_t(PyList_Size(path2)));
if (n==0 || m==0) {
PyErr_SetString(PyExc_ValueError, "One of the two paths doesn't exist.");
return NULL;
}
long i = 0;
j = 0;
while (i<n && j<m) {
if (PyList_GetItem(path1, PyLong_AsSsize_t(PyLong_FromLong(i))) != PyList_GetItem(path2, PyLong_AsSsize_t(PyLong_FromLong(j)))) {
return reinterpret_cast<TreeNode*>(bt->tree->_one_dimensional_array->_data[PyLong_AsLong(PyList_GetItem(path1, PyLong_AsSsize_t(PyLong_FromLong(i-1))))])->key;
}
i += 1;
j += 1;
}

while (i<n && j<m) {
if (PyList_GetItem(path1, PyLong_AsSsize_t(PyLong_FromLong(i))) < PyList_GetItem(path2, PyLong_AsSsize_t(PyLong_FromLong(j)))) {
return reinterpret_cast<TreeNode*>(bt->tree->_one_dimensional_array->_data[PyLong_AsLong(PyList_GetItem(path1, PyLong_AsSsize_t(PyLong_FromLong(n-1))))])->key;
}
else if (PyList_GetItem(path1, PyLong_AsSsize_t(PyLong_FromLong(i))) > PyList_GetItem(path2, PyLong_AsSsize_t(PyLong_FromLong(j)))) {
break;
}
i += 1;
j += 1;
}
return reinterpret_cast<TreeNode*>(bt->tree->_one_dimensional_array->_data[PyLong_AsLong(PyList_GetItem(path2, PyLong_AsSsize_t(PyLong_FromLong(m-1))))])->key;
}

static PyObject* BinarySearchTree_lowest_common_ancestor(BinarySearchTree* self, PyObject* args) {
Py_INCREF(Py_None);
PyObject* j = Py_None;
Py_INCREF(Py_None);
PyObject* k = Py_None;
PyObject* algorithm = PyOne;
if(!PyArg_ParseTuple(args, "OO|O", &j, &k, &algorithm)){ // ret_parent is optional
return NULL;
}

if (algorithm == PyOne) {
return BinarySearchTree__lca_1(self, Py_BuildValue("(OO)",j,k));
}
else {
Py_RETURN_NONE;
}
}

static struct PyMethodDef BinarySearchTree_PyMethodDef[] = {
{"insert", (PyCFunction) BinarySearchTree_insert, METH_VARARGS | METH_KEYWORDS, NULL},
{"delete", (PyCFunction) BinarySearchTree_delete, METH_VARARGS | METH_KEYWORDS, NULL},
{"search", (PyCFunction) BinarySearchTree_search, METH_VARARGS | METH_KEYWORDS, NULL},
{"lower_bound", (PyCFunction) BinarySearchTree_lower_bound, METH_VARARGS | METH_KEYWORDS, NULL},
{"upper_bound", (PyCFunction) BinarySearchTree_upper_bound, METH_VARARGS | METH_KEYWORDS, NULL},
{"_simple_path", (PyCFunction) BinarySearchTree__simple_path, METH_VARARGS, NULL},
{"_lca_1", (PyCFunction) BinarySearchTree__lca_1, METH_VARARGS, NULL},
{"lowest_common_ancestor", (PyCFunction) BinarySearchTree_lowest_common_ancestor, METH_VARARGS, NULL},
{NULL}
};

Expand Down
6 changes: 3 additions & 3 deletions pydatastructs/trees/_backend/cpp/BinaryTree.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,17 +89,17 @@ static PyObject* BinaryTree___new__(PyTypeObject* type, PyObject *args, PyObject
}

static PyObject* BinaryTree_insert(PyTypeObject* type, PyObject *args, PyObject *kwds) {
PyErr_SetString(PyExc_NotImplementedError, "This is an abstract method."); // Currently of type ValueError, change type if needed later
PyErr_SetString(PyExc_NotImplementedError, "This is an abstract method.");
return NULL;
}

static PyObject* BinaryTree_delete(PyTypeObject* type, PyObject *args, PyObject *kwds) {
PyErr_SetString(PyExc_NotImplementedError, "This is an abstract method."); // Currently of type ValueError, change type if needed later
PyErr_SetString(PyExc_NotImplementedError, "This is an abstract method.");
return NULL;
}

static PyObject* BinaryTree_search(PyTypeObject* type, PyObject *args, PyObject *kwds) {
PyErr_SetString(PyExc_NotImplementedError, "This is an abstract method."); // Currently of type ValueError, change type if needed later
PyErr_SetString(PyExc_NotImplementedError, "This is an abstract method.");
return NULL;
}

Expand Down
17 changes: 16 additions & 1 deletion pydatastructs/trees/tests/test_binary_trees.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,11 +112,26 @@ def test_cpp_BST2():
assert str(b2) == "[(7, -8, 8, 1), (4, -1, 1, None), '', '', (6, -6, 6, 5), (None, -4, 4, None), (None, -7, 7, None), (None, -14, 14, None)]"

bl = BST(backend=Backend.CPP)
# bl = BST()
nodes = [50, 30, 90, 70, 100, 60, 80, 55, 20, 40, 15, 10, 16, 17, 18]
for node in nodes:
bl.insert(node, node)
assert str(bl) == "[(1, 50, 50, 2), (8, 30, 30, 9), (3, 90, 90, 4), (5, 70, 70, 6), (None, 100, 100, None), (7, 60, 60, None), (None, 80, 80, None), (None, 55, 55, None), (10, 20, 20, None), (None, 40, 40, None), (11, 15, 15, 12), (None, 10, 10, None), (None, 16, 16, 13), (None, 17, 17, 14), (None, 18, 18, None)]"

assert bl.lowest_common_ancestor(80, 55, 1) == 70
assert bl.lowest_common_ancestor(60, 70, 1) == 70
assert bl.lowest_common_ancestor(18, 18, 1) == 18
assert bl.lowest_common_ancestor(40, 90, 1) == 50

assert bl.lowest_common_ancestor(18, 10, 1) == 15
assert bl.lowest_common_ancestor(55, 100, 1) == 90
assert bl.lowest_common_ancestor(16, 80, 1) == 50
assert bl.lowest_common_ancestor(30, 55, 1) == 50

assert raises(ValueError, lambda: bl.lowest_common_ancestor(60, 200, 1))
assert raises(ValueError, lambda: bl.lowest_common_ancestor(200, 60, 1))
assert raises(ValueError, lambda: bl.lowest_common_ancestor(-3, 4, 1))

b3 = BST(backend=Backend.CPP)
# b3 = BST()
b3.insert(10, 10)
Expand All @@ -135,7 +150,7 @@ def test_cpp_BST2():
test_cpp_BST2()


################### Actual Tests below ###################
################### Python Tests below ###################

def test_BinarySearchTree():
BST = BinarySearchTree
Expand Down

0 comments on commit 21c74f5

Please sign in to comment.