From ca0c042d3fa94471bae531b6027258bcdad0f729 Mon Sep 17 00:00:00 2001 From: Kishan-Ved Date: Mon, 24 Jun 2024 16:04:47 +0530 Subject: [PATCH] Splay Trees split() --- .../trees/_backend/cpp/SplayTree.hpp | 71 +++++++++++++++++++ pydatastructs/trees/binary_trees.py | 2 +- .../trees/tests/test_binary_trees.py | 27 +++---- 3 files changed, 86 insertions(+), 14 deletions(-) diff --git a/pydatastructs/trees/_backend/cpp/SplayTree.hpp b/pydatastructs/trees/_backend/cpp/SplayTree.hpp index 5524101a..00eaaed9 100644 --- a/pydatastructs/trees/_backend/cpp/SplayTree.hpp +++ b/pydatastructs/trees/_backend/cpp/SplayTree.hpp @@ -9,6 +9,7 @@ #include "../../../utils/_backend/cpp/TreeNode.hpp" #include "../../../linear_data_structures/_backend/cpp/arrays/ArrayForTrees.hpp" #include "../../../linear_data_structures/_backend/cpp/arrays/DynamicOneDimensionalArray.hpp" +#include "BinaryTreeTraversal.hpp" #include "BinarySearchTree.hpp" #include "SelfBalancingBinaryTree.hpp" @@ -216,14 +217,82 @@ static PyObject* SplayTree_join(SplayTree *self, PyObject* args) { Py_RETURN_NONE; } +static PyObject* SplayTree__pre_order(SplayTree* self, PyObject *args) { + long node = PyLong_AsLong(PyObject_GetItem(args, PyZero)); + PyObject* visit = PyList_New(0); + ArrayForTrees* tree = self->sbbt->bst->binary_tree->tree; + long size = self->sbbt->bst->binary_tree->size; + std::stack s; + s.push(node); + + while (!s.empty()) { + node = s.top(); + s.pop(); + TreeNode* curr_node = reinterpret_cast(tree->_one_dimensional_array->_data[node]); + PyList_Append(visit, reinterpret_cast(curr_node)); + if (curr_node->right != Py_None) { + s.push(PyLong_AsLong(curr_node->right)); + } + if (curr_node->left != Py_None) { + s.push(PyLong_AsLong(curr_node->left)); + } + } + return visit; +} + +static PyObject* SplayTree_split(SplayTree *self, PyObject* args) { + PyObject* x = PyObject_GetItem(args, PyZero); + BinaryTree* bt = self->sbbt->bst->binary_tree; + + PyObject* kwd_parent = PyDict_New(); + PyDict_SetItemString(kwd_parent, "parent", PyLong_FromLong(1)); + PyObject* tup = SelfBalancingBinaryTree_search(self->sbbt, Py_BuildValue("(O)", x), kwd_parent); + PyObject* e = PyTuple_GetItem(tup, 0); + PyObject* p = PyTuple_GetItem(tup, 1); + if (e == Py_None) { + Py_RETURN_NONE; + } + SplayTree_splay(self, Py_BuildValue("(OO)", e, p)); + + Py_INCREF(Py_None); + Py_INCREF(Py_None); + // SplayTree* other = reinterpret_cast(SplayTree___new__(self->type, Py_BuildValue("(OO)", Py_None, Py_None), PyDict_New())); + SplayTree* other = reinterpret_cast(PyObject_GetItem(args, PyOne)); + + if (reinterpret_cast(bt->tree->_one_dimensional_array->_data[PyLong_AsLong(bt->root_idx)])->right != Py_None) { + // if (PyType_Ready(&BinaryTreeTraversalType) < 0) { // This has to be present to finalize a type object. This should be called on all type objects to finish their initialization. + // return NULL; + // } + // BinaryTreeTraversal* traverse = reinterpret_cast(BinaryTreeTraversal___new__(&BinaryTreeTraversalType, Py_BuildValue("(O)", self), PyDict_New())); + // PyObject* kwd_dict = PyDict_New(); + // PyDict_SetItemString(kwd_dict, "node", reinterpret_cast(bt->tree->_one_dimensional_array->_data[PyLong_AsLong(bt->root_idx)])->right); + // PyDict_SetItemString(kwd_dict, "order", PyUnicode_FromString("pre_order")); + // PyObject* elements = BinaryTreeTraversal_depth_first_search(traverse, Py_BuildValue("()"), kwd_dict); + PyObject* elements = SplayTree__pre_order(self, Py_BuildValue("(O)", reinterpret_cast(bt->tree->_one_dimensional_array->_data[PyLong_AsLong(bt->root_idx)])->right)); + for (int i=0; isbbt, Py_BuildValue("(OO)", reinterpret_cast( PyList_GetItem(elements, i))->key, reinterpret_cast( PyList_GetItem(elements, i))->data)); + } + for (int j=PyList_Size(elements)-1; j>-1; j--) { + tup = SelfBalancingBinaryTree_search(self->sbbt, Py_BuildValue("(O)", reinterpret_cast( PyList_GetItem(elements, j))->key), kwd_parent); + e = PyTuple_GetItem(tup, 0); + p = PyTuple_GetItem(tup, 1); + bt->tree->_one_dimensional_array->_data[PyLong_AsLong(e)] = Py_None; + } + reinterpret_cast(bt->tree->_one_dimensional_array->_data[PyLong_AsLong(bt->root_idx)])->right = Py_None; + } + + return reinterpret_cast(other); +} static struct PyMethodDef SplayTree_PyMethodDef[] = { {"insert", (PyCFunction) SplayTree_insert, METH_VARARGS, NULL}, {"delete", (PyCFunction) SplayTree_delete, METH_VARARGS, NULL}, {"join", (PyCFunction) SplayTree_join, METH_VARARGS, NULL}, + {"split", (PyCFunction) SplayTree_split, METH_VARARGS, NULL}, {NULL} }; + static PyMemberDef SplayTree_PyMemberDef[] = { {"tree", T_OBJECT_EX, offsetof(SplayTree, tree), 0, "tree"}, {NULL} /* Sentinel */ @@ -270,4 +339,6 @@ static PyTypeObject SplayTreeType = { /* tp_new */ SplayTree___new__, }; + + #endif diff --git a/pydatastructs/trees/binary_trees.py b/pydatastructs/trees/binary_trees.py index d914b8ab..c0977aff 100644 --- a/pydatastructs/trees/binary_trees.py +++ b/pydatastructs/trees/binary_trees.py @@ -1145,7 +1145,7 @@ def join(self, other): self.tree[self.root_idx].right = \ other.root_idx + idx_update - def split(self, x): + def split(self, x, unused): """ Splits current splay tree into two trees such that one tree contains nodes with key less than or equal to x and the other tree containing diff --git a/pydatastructs/trees/tests/test_binary_trees.py b/pydatastructs/trees/tests/test_binary_trees.py index 062451e0..568021d3 100644 --- a/pydatastructs/trees/tests/test_binary_trees.py +++ b/pydatastructs/trees/tests/test_binary_trees.py @@ -535,19 +535,20 @@ def _test_SplayTree(backend): # assert [node.key for node in in_order] == [20, 30, 50, 55, 100, 200, 1000, 2000] # assert [node.key for node in pre_order] == [200, 55, 50, 30, 20, 100, 2000, 1000] - # s = t.split(200) - - # trav4 = BinaryTreeTraversal(s) - # in_order = trav4.depth_first_search(order='in_order') - # pre_order = trav4.depth_first_search(order='pre_order') - # assert [node.key for node in in_order] == [1000, 2000] - # assert [node.key for node in pre_order] == [2000, 1000] - - # trav5 = BinaryTreeTraversal(t) - # in_order = trav5.depth_first_search(order='in_order') - # pre_order = trav5.depth_first_search(order='pre_order') - # assert [node.key for node in in_order] == [20, 30, 50, 55, 100, 200] - # assert [node.key for node in pre_order] == [200, 55, 50, 30, 20, 100] + s = t.split(200, SplayTree(backend=backend)) + assert str(s) == "[(1, 2000, 2000, None), (None, 1000, 1000, None)]" + + trav4 = BinaryTreeTraversal(s, backend=backend) + in_order = trav4.depth_first_search(order='in_order') + pre_order = trav4.depth_first_search(order='pre_order') + assert [node.key for node in in_order] == [1000, 2000] + assert [node.key for node in pre_order] == [2000, 1000] + + trav5 = BinaryTreeTraversal(t, backend=backend) + in_order = trav5.depth_first_search(order='in_order') + pre_order = trav5.depth_first_search(order='pre_order') + assert [node.key for node in in_order] == [20, 30, 50, 55, 100, 200] + assert [node.key for node in pre_order] == [200, 55, 50, 30, 20, 100] def test_SplayTree(): _test_SplayTree(Backend.PYTHON)