Skip to content

Commit 21c74f5

Browse files
committed
BST Lowest Common Ancestor by lca1 done and tested
1 parent bda0dd1 commit 21c74f5

File tree

3 files changed

+75
-4
lines changed

3 files changed

+75
-4
lines changed

pydatastructs/trees/_backend/cpp/BinarySearchTree.hpp

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,13 +428,69 @@ static PyObject* BinarySearchTree__simple_path(BinarySearchTree* self, PyObject
428428
return path;
429429
}
430430

431+
static PyObject* BinarySearchTree__lca_1(BinarySearchTree* self, PyObject* args) {
432+
long j = PyLong_AsLong(PyObject_GetItem(args, PyZero));
433+
long k = PyLong_AsLong(PyObject_GetItem(args, PyOne));
434+
BinaryTree* bt = self->binary_tree;
435+
PyObject* root = bt->root_idx;
436+
PyObject* path1 = BinarySearchTree__simple_path(self, Py_BuildValue("(OO)",PyLong_FromLong(j),root));
437+
PyObject* path2 = BinarySearchTree__simple_path(self, Py_BuildValue("(OO)",PyLong_FromLong(k),root));
438+
long n = PyLong_AsLong(PyLong_FromSsize_t(PyList_Size(path1)));
439+
long m = PyLong_AsLong(PyLong_FromSsize_t(PyList_Size(path2)));
440+
if (n==0 || m==0) {
441+
PyErr_SetString(PyExc_ValueError, "One of the two paths doesn't exist.");
442+
return NULL;
443+
}
444+
long i = 0;
445+
j = 0;
446+
while (i<n && j<m) {
447+
if (PyList_GetItem(path1, PyLong_AsSsize_t(PyLong_FromLong(i))) != PyList_GetItem(path2, PyLong_AsSsize_t(PyLong_FromLong(j)))) {
448+
return reinterpret_cast<TreeNode*>(bt->tree->_one_dimensional_array->_data[PyLong_AsLong(PyList_GetItem(path1, PyLong_AsSsize_t(PyLong_FromLong(i-1))))])->key;
449+
}
450+
i += 1;
451+
j += 1;
452+
}
453+
454+
while (i<n && j<m) {
455+
if (PyList_GetItem(path1, PyLong_AsSsize_t(PyLong_FromLong(i))) < PyList_GetItem(path2, PyLong_AsSsize_t(PyLong_FromLong(j)))) {
456+
return reinterpret_cast<TreeNode*>(bt->tree->_one_dimensional_array->_data[PyLong_AsLong(PyList_GetItem(path1, PyLong_AsSsize_t(PyLong_FromLong(n-1))))])->key;
457+
}
458+
else if (PyList_GetItem(path1, PyLong_AsSsize_t(PyLong_FromLong(i))) > PyList_GetItem(path2, PyLong_AsSsize_t(PyLong_FromLong(j)))) {
459+
break;
460+
}
461+
i += 1;
462+
j += 1;
463+
}
464+
return reinterpret_cast<TreeNode*>(bt->tree->_one_dimensional_array->_data[PyLong_AsLong(PyList_GetItem(path2, PyLong_AsSsize_t(PyLong_FromLong(m-1))))])->key;
465+
}
466+
467+
static PyObject* BinarySearchTree_lowest_common_ancestor(BinarySearchTree* self, PyObject* args) {
468+
Py_INCREF(Py_None);
469+
PyObject* j = Py_None;
470+
Py_INCREF(Py_None);
471+
PyObject* k = Py_None;
472+
PyObject* algorithm = PyOne;
473+
if(!PyArg_ParseTuple(args, "OO|O", &j, &k, &algorithm)){ // ret_parent is optional
474+
return NULL;
475+
}
476+
477+
if (algorithm == PyOne) {
478+
return BinarySearchTree__lca_1(self, Py_BuildValue("(OO)",j,k));
479+
}
480+
else {
481+
Py_RETURN_NONE;
482+
}
483+
}
484+
431485
static struct PyMethodDef BinarySearchTree_PyMethodDef[] = {
432486
{"insert", (PyCFunction) BinarySearchTree_insert, METH_VARARGS | METH_KEYWORDS, NULL},
433487
{"delete", (PyCFunction) BinarySearchTree_delete, METH_VARARGS | METH_KEYWORDS, NULL},
434488
{"search", (PyCFunction) BinarySearchTree_search, METH_VARARGS | METH_KEYWORDS, NULL},
435489
{"lower_bound", (PyCFunction) BinarySearchTree_lower_bound, METH_VARARGS | METH_KEYWORDS, NULL},
436490
{"upper_bound", (PyCFunction) BinarySearchTree_upper_bound, METH_VARARGS | METH_KEYWORDS, NULL},
437491
{"_simple_path", (PyCFunction) BinarySearchTree__simple_path, METH_VARARGS, NULL},
492+
{"_lca_1", (PyCFunction) BinarySearchTree__lca_1, METH_VARARGS, NULL},
493+
{"lowest_common_ancestor", (PyCFunction) BinarySearchTree_lowest_common_ancestor, METH_VARARGS, NULL},
438494
{NULL}
439495
};
440496

pydatastructs/trees/_backend/cpp/BinaryTree.hpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,17 +89,17 @@ static PyObject* BinaryTree___new__(PyTypeObject* type, PyObject *args, PyObject
8989
}
9090

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

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

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

pydatastructs/trees/tests/test_binary_trees.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,11 +112,26 @@ def test_cpp_BST2():
112112
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)]"
113113

114114
bl = BST(backend=Backend.CPP)
115+
# bl = BST()
115116
nodes = [50, 30, 90, 70, 100, 60, 80, 55, 20, 40, 15, 10, 16, 17, 18]
116117
for node in nodes:
117118
bl.insert(node, node)
118119
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)]"
119120

121+
assert bl.lowest_common_ancestor(80, 55, 1) == 70
122+
assert bl.lowest_common_ancestor(60, 70, 1) == 70
123+
assert bl.lowest_common_ancestor(18, 18, 1) == 18
124+
assert bl.lowest_common_ancestor(40, 90, 1) == 50
125+
126+
assert bl.lowest_common_ancestor(18, 10, 1) == 15
127+
assert bl.lowest_common_ancestor(55, 100, 1) == 90
128+
assert bl.lowest_common_ancestor(16, 80, 1) == 50
129+
assert bl.lowest_common_ancestor(30, 55, 1) == 50
130+
131+
assert raises(ValueError, lambda: bl.lowest_common_ancestor(60, 200, 1))
132+
assert raises(ValueError, lambda: bl.lowest_common_ancestor(200, 60, 1))
133+
assert raises(ValueError, lambda: bl.lowest_common_ancestor(-3, 4, 1))
134+
120135
b3 = BST(backend=Backend.CPP)
121136
# b3 = BST()
122137
b3.insert(10, 10)
@@ -135,7 +150,7 @@ def test_cpp_BST2():
135150
test_cpp_BST2()
136151

137152

138-
################### Actual Tests below ###################
153+
################### Python Tests below ###################
139154

140155
def test_BinarySearchTree():
141156
BST = BinarySearchTree

0 commit comments

Comments
 (0)