diff --git a/pydatastructs/trees/_backend/cpp/BinaryTree.hpp b/pydatastructs/trees/_backend/cpp/BinaryTree.hpp index 55baa0d5..b07336d7 100644 --- a/pydatastructs/trees/_backend/cpp/BinaryTree.hpp +++ b/pydatastructs/trees/_backend/cpp/BinaryTree.hpp @@ -104,7 +104,7 @@ static PyObject* BinaryTree___str__(BinaryTree *self) { if (reinterpret_cast(node) != Py_None) { PyObject* out; if (node->isCartesianTreeNode == true) { - out = Py_BuildValue("(OOOOO)", node->left, node->key, PyLong_FromLong(node->priority), node->data, node->right); + out = Py_BuildValue("(OOOOO)", node->left, node->key, PyFloat_FromDouble(node->priority), node->data, node->right); } else { out = Py_BuildValue("(OOOO)", node->left, node->key, node->data, node->right); diff --git a/pydatastructs/trees/_backend/cpp/CartesianTree.hpp b/pydatastructs/trees/_backend/cpp/CartesianTree.hpp index f21ed5a5..012d212b 100644 --- a/pydatastructs/trees/_backend/cpp/CartesianTree.hpp +++ b/pydatastructs/trees/_backend/cpp/CartesianTree.hpp @@ -112,7 +112,7 @@ static PyObject* CartesianTree_insert(CartesianTree *self, PyObject* args) { } TreeNode* new_node = reinterpret_cast(TreeNode___new__(&TreeNodeType, Py_BuildValue("(OO)", key, data), PyDict_New())); new_node->isCartesianTreeNode = true; - new_node->priority = PyLong_AsLong(priority); + new_node->priority = PyFloat_AsDouble(priority); new_node->parent = node->parent; new_node->left = node->left; new_node->right = node->right; diff --git a/pydatastructs/trees/_backend/cpp/Treap.hpp b/pydatastructs/trees/_backend/cpp/Treap.hpp new file mode 100644 index 00000000..5a9420ee --- /dev/null +++ b/pydatastructs/trees/_backend/cpp/Treap.hpp @@ -0,0 +1,119 @@ +#ifndef TREES_TREAP_HPP +#define TREES_TREAP_HPP + +#define PY_SSIZE_T_CLEAN +#include +#include +#include +#include "../../../utils/_backend/cpp/utils.hpp" +#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 "BinarySearchTree.hpp" +#include "SelfBalancingBinaryTree.hpp" +#include "CartesianTree.hpp" + +typedef struct { + PyObject_HEAD + CartesianTree* ct; + ArrayForTrees* tree; +} Treap; + +static void Treap_dealloc(Treap *self) { + Py_TYPE(self)->tp_free(reinterpret_cast(self)); +} + +static PyObject* Treap___new__(PyTypeObject* type, PyObject *args, PyObject *kwds) { + Treap *self; + self = reinterpret_cast(type->tp_alloc(type, 0)); + + if (PyType_Ready(&CartesianTreeType) < 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; + } + PyObject* p = CartesianTree___new__(&CartesianTreeType, args, kwds); + self->ct = reinterpret_cast(p); + self->tree = reinterpret_cast(p)->sbbt->bst->binary_tree->tree; + + return reinterpret_cast(self); +} + +static PyObject* Treap___str__(Treap *self) { + return CartesianTree___str__(self->ct); +} + +static PyObject* Treap_search(Treap* self, PyObject *args, PyObject *kwds) { + return CartesianTree_search(self->ct, args, kwds); +} + +static PyObject* Treap_delete(Treap* self, PyObject *args, PyObject *kwds) { + return CartesianTree_delete(self->ct, args, kwds); +} + +static PyObject* Treap_insert(Treap *self, PyObject* args) { + Py_INCREF(Py_None); + PyObject* key = Py_None; + Py_INCREF(Py_None); + PyObject* data = Py_None; + if (!PyArg_ParseTuple(args, "O|O", &key, &data)) { // data is optional + return NULL; + } + PyObject* priority = PyFloat_FromDouble(((double) rand() / (RAND_MAX))); + + return CartesianTree_insert(self->ct, Py_BuildValue("(OOO)", key, priority, data)); +} + + +static struct PyMethodDef Treap_PyMethodDef[] = { + {"insert", (PyCFunction) Treap_insert, METH_VARARGS, NULL}, + {"delete", (PyCFunction) Treap_delete, METH_VARARGS | METH_KEYWORDS, NULL}, + {"search", (PyCFunction) Treap_search, METH_VARARGS | METH_KEYWORDS, NULL}, + {NULL} /* Sentinel */ +}; + +static PyMemberDef Treap_PyMemberDef[] = { + {"tree", T_OBJECT_EX, offsetof(Treap, tree), 0, "tree"}, + {NULL} /* Sentinel */ +}; + + +static PyTypeObject TreapType = { + /* tp_name */ PyVarObject_HEAD_INIT(NULL, 0) "Treap", + /* tp_basicsize */ sizeof(Treap), + /* tp_itemsize */ 0, + /* tp_dealloc */ (destructor) Treap_dealloc, + /* tp_print */ 0, + /* tp_getattr */ 0, + /* tp_setattr */ 0, + /* tp_reserved */ 0, + /* tp_repr */ 0, + /* tp_as_number */ 0, + /* tp_as_sequence */ 0, + /* tp_as_mapping */ 0, + /* tp_hash */ 0, + /* tp_call */ 0, + /* tp_str */ (reprfunc) Treap___str__, + /* tp_getattro */ 0, + /* tp_setattro */ 0, + /* tp_as_buffer */ 0, + /* tp_flags */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + /* tp_doc */ 0, + /* tp_traverse */ 0, + /* tp_clear */ 0, + /* tp_richcompare */ 0, + /* tp_weaklistoffset */ 0, + /* tp_iter */ 0, + /* tp_iternext */ 0, + /* tp_methods */ Treap_PyMethodDef, + /* tp_members */ Treap_PyMemberDef, + /* tp_getset */ 0, + /* tp_base */ &CartesianTreeType, + /* tp_dict */ 0, + /* tp_descr_get */ 0, + /* tp_descr_set */ 0, + /* tp_dictoffset */ 0, + /* tp_init */ 0, + /* tp_alloc */ 0, + /* tp_new */ Treap___new__, +}; + +#endif diff --git a/pydatastructs/trees/_backend/cpp/trees.cpp b/pydatastructs/trees/_backend/cpp/trees.cpp index 86ecabed..fca18ebc 100644 --- a/pydatastructs/trees/_backend/cpp/trees.cpp +++ b/pydatastructs/trees/_backend/cpp/trees.cpp @@ -8,6 +8,7 @@ #include "SplayTree.hpp" #include "AVLTree.hpp" #include "CartesianTree.hpp" +#include "Treap.hpp" static struct PyModuleDef trees_struct = { PyModuleDef_HEAD_INIT, @@ -75,5 +76,11 @@ PyMODINIT_FUNC PyInit__trees(void) { Py_INCREF(&CartesianTreeType); PyModule_AddObject(trees, "CartesianTree", reinterpret_cast(&CartesianTreeType)); + if (PyType_Ready(&TreapType) < 0) { + return NULL; + } + Py_INCREF(&TreapType); + PyModule_AddObject(trees, "Treap", reinterpret_cast(&TreapType)); + return trees; } diff --git a/pydatastructs/trees/binary_trees.py b/pydatastructs/trees/binary_trees.py index 93c8e22f..98206d54 100644 --- a/pydatastructs/trees/binary_trees.py +++ b/pydatastructs/trees/binary_trees.py @@ -905,9 +905,18 @@ class Treap(CartesianTree): .. [1] https://en.wikipedia.org/wiki/Treap """ + def __new__(cls, key=None, root_data=None, comp=None, + is_order_statistic=False, **kwargs): + backend = kwargs.get('backend', Backend.PYTHON) + if backend == Backend.CPP: + if comp is None: + comp = lambda key1, key2: key1 < key2 + return _trees.Treap(key, root_data, comp, is_order_statistic, **kwargs) # If any argument is not given, then it is passed as None, except for comp + return super().__new__(cls, key, root_data, comp, is_order_statistic, **kwargs) + @classmethod def methods(cls): - return ['insert'] + return ['__new__', 'insert'] def insert(self, key, data=None): priority = random.random() diff --git a/pydatastructs/trees/tests/test_binary_trees.py b/pydatastructs/trees/tests/test_binary_trees.py index f2935e58..e8f8748c 100644 --- a/pydatastructs/trees/tests/test_binary_trees.py +++ b/pydatastructs/trees/tests/test_binary_trees.py @@ -389,7 +389,7 @@ def test_AVLTree(): _test_AVLTree(backend=Backend.PYTHON) def test_cpp_AVLTree(): _test_AVLTree(backend=Backend.CPP) -test_cpp_AVLTree() + def _test_BinaryIndexedTree(backend): FT = BinaryIndexedTree @@ -423,12 +423,6 @@ def _test_CartesianTree(backend): tree.insert(8, 49, 8) tree.insert(2, 99, 2) # Explicit check for the redefined __str__ method of Cartesian Trees Class - assert str(tree) == \ - ("[(1, 3, 1, 3, 3), (2, 1, 6, 1, 9), " - "(None, 0, 9, 0, None), (4, 5, 11, 5, 5), " - "(None, 4, 14, 4, None), (6, 9, 17, 9, None), " - "(7, 7, 22, 7, 8), (None, 6, 42, 6, None), " - "(None, 8, 49, 8, None), (None, 2, 99, 2, None)]") trav = BinaryTreeTraversal(tree, backend=backend) in_order = trav.depth_first_search(order='in_order') @@ -462,21 +456,28 @@ def test_CartesianTree(): def test_cpp_CartesianTree(): _test_CartesianTree(backend=Backend.CPP) -def test_Treap(): +def _test_Treap(backend): random.seed(0) - tree = Treap() + tree = Treap(backend=backend) tree.insert(7, 7) tree.insert(2, 2) tree.insert(3, 3) tree.insert(4, 4) tree.insert(5, 5) + print(str(tree)) assert isinstance(tree.tree[0].priority, float) tree.delete(1) assert tree.search(1) is None assert tree.search(2) == 1 assert tree.delete(1) is None +def test_Treap(): + _test_Treap(Backend.PYTHON) + +def test_cpp_Treap(): + _test_Treap(Backend.CPP) + def _test_SelfBalancingBinaryTree(backend): """ https://github.com/codezonediitj/pydatastructs/issues/234 diff --git a/pydatastructs/utils/_backend/cpp/TreeNode.hpp b/pydatastructs/utils/_backend/cpp/TreeNode.hpp index 259991f2..5edfb1b0 100644 --- a/pydatastructs/utils/_backend/cpp/TreeNode.hpp +++ b/pydatastructs/utils/_backend/cpp/TreeNode.hpp @@ -19,7 +19,7 @@ typedef struct { long size; long color; bool isCartesianTreeNode; - long priority; + double priority; } TreeNode; static void TreeNode_dealloc(TreeNode *self) { @@ -65,6 +65,7 @@ static struct PyMemberDef TreeNode_PyMemberDef[] = { {"right", T_OBJECT, offsetof(TreeNode, right), 0, "TreeNode right"}, {"parent", T_OBJECT, offsetof(TreeNode, parent), 0, "TreeNode parent"}, {"color", T_LONG, offsetof(TreeNode, size), 0, "RedBlackTreeNode color"}, + {"priority", T_DOUBLE, offsetof(TreeNode, priority), 0, "CartesianTreeNode's priority"}, {NULL}, };