Skip to content

Commit

Permalink
delete() for AVL Trees
Browse files Browse the repository at this point in the history
  • Loading branch information
Kishan-Ved committed Jul 2, 2024
1 parent 8e442e0 commit 59358a5
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 30 deletions.
56 changes: 56 additions & 0 deletions pydatastructs/trees/_backend/cpp/AVLTree.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -251,9 +251,65 @@ static PyObject* AVLTree_select(AVLTree* self, PyObject *args) {
return BinarySearchTree_select(self->sbbt->bst, args);
}

static PyObject* AVLTree__balance_delete(AVLTree* self, PyObject *args) {
PyObject* start_idx = PyObject_GetItem(args, PyZero);
PyObject* key = PyObject_GetItem(args, PyOne);
BinaryTree* bt = self->sbbt->bst->binary_tree;

PyObject* walk = start_idx;
while (walk != Py_None) {
long lh = AVLTree_left_height(self, Py_BuildValue("(O)", bt->tree->_one_dimensional_array->_data[PyLong_AsLong(walk)]));
long rh = AVLTree_right_height(self, Py_BuildValue("(O)", bt->tree->_one_dimensional_array->_data[PyLong_AsLong(walk)]));
reinterpret_cast<TreeNode*>(bt->tree->_one_dimensional_array->_data[PyLong_AsLong(walk)])->height = std::max(lh, rh) + 1;

if (bt->is_order_statistic == true) {
long ls = BinarySearchTree_left_size(self->sbbt->bst, reinterpret_cast<TreeNode*>(bt->tree->_one_dimensional_array->_data[PyLong_AsLong(walk)]));
long rs = BinarySearchTree_right_size(self->sbbt->bst, reinterpret_cast<TreeNode*>(bt->tree->_one_dimensional_array->_data[PyLong_AsLong(walk)]));
reinterpret_cast<TreeNode*>(bt->tree->_one_dimensional_array->_data[PyLong_AsLong(walk)])->size = ls + rs + 1;
}

long bf = PyLong_AsLong(AVLTree_balance_factor(self, Py_BuildValue("(O)", bt->tree->_one_dimensional_array->_data[PyLong_AsLong(walk)])));
if (bf != 1 && bf != 0 && bf != -1) {
if (bf < 0) {
PyObject* b = reinterpret_cast<TreeNode*>(bt->tree->_one_dimensional_array->_data[PyLong_AsLong(walk)])->left;
if (PyLong_AsLong(AVLTree_balance_factor(self, Py_BuildValue("(O)", bt->tree->_one_dimensional_array->_data[PyLong_AsLong(b)]))) <= 0) {
AVLTree__right_rotate(self, Py_BuildValue("(OO)", walk, b));
}
else {
AVLTree__left_right_rotate(self, Py_BuildValue("(OO)", walk, b));
}
}
else {
PyObject* b = reinterpret_cast<TreeNode*>(bt->tree->_one_dimensional_array->_data[PyLong_AsLong(walk)])->right;
if (PyLong_AsLong(AVLTree_balance_factor(self, Py_BuildValue("(O)", bt->tree->_one_dimensional_array->_data[PyLong_AsLong(b)]))) >= 0) {
AVLTree__left_rotate(self, Py_BuildValue("(OO)", walk, b));
}
else {
AVLTree__right_left_rotate(self, Py_BuildValue("(OO)", walk, b));
}
}
}
walk = reinterpret_cast<TreeNode*>(bt->tree->_one_dimensional_array->_data[PyLong_AsLong(walk)])->parent;
}

Py_RETURN_NONE;
}

static PyObject* AVLTree_delete(AVLTree* self, PyObject *args, PyObject *kwds) {
PyObject* key = PyObject_GetItem(args, PyZero);

PyObject* kwd_bal = PyDict_New();
PyDict_SetItemString(kwd_bal, "balancing_info", PyLong_FromLong(1));
PyObject* a = SelfBalancingBinaryTree_delete(self->sbbt, Py_BuildValue("(O)", key), kwd_bal);
AVLTree__balance_delete(self, Py_BuildValue("(OO)", a, key));

Py_RETURN_TRUE;
}

static struct PyMethodDef AVLTree_PyMethodDef[] = {
{"search", (PyCFunction) AVLTree_search, METH_VARARGS | METH_KEYWORDS, NULL},
{"insert", (PyCFunction) AVLTree_insert, METH_VARARGS, NULL},
{"delete", (PyCFunction) AVLTree_delete, METH_VARARGS, NULL},
{"set_tree", (PyCFunction) AVLTree_set_tree, METH_VARARGS, NULL},
{"balance_factor", (PyCFunction) AVLTree_balance_factor, METH_VARARGS, NULL},
{"rank", (PyCFunction) AVLTree_rank, METH_VARARGS, NULL},
Expand Down
57 changes: 27 additions & 30 deletions pydatastructs/trees/tests/test_binary_trees.py
Original file line number Diff line number Diff line change
Expand Up @@ -350,47 +350,44 @@ def test_select_rank(expected_output):
assert output == expected_ranks

test_select_rank([2, 3, 5, 9, 10, 11, 12, 13, 15, 17, 18, 20, 30, 33])
# a5.delete(9)
# a5.delete(13)
# a5.delete(20)
a5.delete(9)
a5.delete(13)
a5.delete(20)

trav = BinaryTreeTraversal(a5, backend=backend)
in_order = trav.depth_first_search(order='in_order')
pre_order = trav.depth_first_search(order='pre_order')
# assert [node.key for node in in_order] == [2, 3, 5, 10, 11, 12, 15, 17, 18, 30, 33]
# assert [node.key for node in pre_order] == [17, 10, 3, 2, 5, 12, 11, 15, 30, 18, 33]

# test_select_rank([2, 3, 5, 10, 11, 12, 15, 17, 18, 30, 33])
# a5.delete(10)
# a5.delete(17)
# test_select_rank([2, 3, 5, 11, 12, 15, 18, 30, 33])
# a5.delete(11)
# a5.delete(30)
# test_select_rank([2, 3, 5, 12, 15, 18, 33])
# a5.delete(12)
# test_select_rank([2, 3, 5, 15, 18, 33])
# a5.delete(15)
# test_select_rank([2, 3, 5, 18, 33])
# a5.delete(18)
# test_select_rank([2, 3, 5, 33])
# a5.delete(33)
# test_select_rank([2, 3, 5])
# a5.delete(5)
# test_select_rank([2, 3])
# a5.delete(3)
# test_select_rank([2])
# a5.delete(2)
# test_select_rank([])
assert [node.key for node in in_order] == [2, 3, 5, 10, 11, 12, 15, 17, 18, 30, 33]
assert [node.key for node in pre_order] == [17, 10, 3, 2, 5, 12, 11, 15, 30, 18, 33]

test_select_rank([2, 3, 5, 10, 11, 12, 15, 17, 18, 30, 33])
a5.delete(10)
a5.delete(17)
test_select_rank([2, 3, 5, 11, 12, 15, 18, 30, 33])
a5.delete(11)
a5.delete(30)
test_select_rank([2, 3, 5, 12, 15, 18, 33])
a5.delete(12)
test_select_rank([2, 3, 5, 15, 18, 33])
a5.delete(15)
test_select_rank([2, 3, 5, 18, 33])
a5.delete(18)
test_select_rank([2, 3, 5, 33])
a5.delete(33)
test_select_rank([2, 3, 5])
a5.delete(5)
test_select_rank([2, 3])
a5.delete(3)
test_select_rank([2])
a5.delete(2)
test_select_rank([])

def test_AVLTree():
_test_AVLTree(backend=Backend.PYTHON)

def test_cpp_AVLTree():
_test_AVLTree(backend=Backend.CPP)

# test_AVLTree()
# test_cpp_AVLTree()

def _test_BinaryIndexedTree(backend):

FT = BinaryIndexedTree
Expand Down

0 comments on commit 59358a5

Please sign in to comment.