diff --git a/pydatastructs/trees/_backend/__init__.py b/pydatastructs/trees/_backend/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/pydatastructs/trees/_backend/cpp/binary_search_tree.cpp b/pydatastructs/trees/_backend/cpp/binary_search_tree.cpp new file mode 100644 index 000000000..130aeadd0 --- /dev/null +++ b/pydatastructs/trees/_backend/cpp/binary_search_tree.cpp @@ -0,0 +1,179 @@ +#include +#include + +// Define TreeNode struct. +// Defines a C struct TreeNode that represents a node in the binary search tree. +// It contains pointers to key, data, left, right, and parent. +typedef struct { + PyObject_HEAD + PyObject* key; + PyObject* data; + PyObject* left; + PyObject* right; + PyObject* parent; + PyObject* size; +} TreeNode; + +// Define BinarySearchTree class. +// Defines a C struct BinarySearchTree that represents the binary search tree. +// It extends the BinaryTree class. +typedef struct { + PyObject_VAR_HEAD + PyObject* left_size; + PyObject* right_size; + PyObject* _update_size; + PyObject* insert; + PyObject* search; + PyObject* _bound_helper; + PyObject* lower_bound; + PyObject* tree; // Define tree attribute +} BinarySearchTree; + +// Deallocation function for BinarySearchTree. +// Defines a deallocation function for BinarySearchTree. +static void BinarySearchTree_dealloc(BinarySearchTree* self) { + Py_XDECREF(self->left_size); + Py_XDECREF(self->right_size); + Py_XDECREF(self->_update_size); + Py_XDECREF(self->insert); + Py_XDECREF(self->search); + Py_XDECREF(self->_bound_helper); + Py_XDECREF(self->lower_bound); + Py_XDECREF(self->tree); // Release memory for the tree attribute + + Py_TYPE(self)->tp_free(reinterpret_cast(self)); +} + +// Object creation function for BinarySearchTree. +// Defines a new object creation function for BinarySearchTree. +static PyObject* BinarySearchTree_new(PyTypeObject* type, PyObject* args, PyObject* kwds) { + BinarySearchTree* self; + self = reinterpret_cast(type->tp_alloc(type, 0)); + + // Initialize tree attribute as an empty list + if (self != NULL) { + self->tree = PyList_New(0); + if (self->tree == NULL) { + Py_DECREF(self); + return NULL; + } + } + return reinterpret_cast(self); +} + +// Method to update the size of nodes in the tree. +static PyObject* BinarySearchTree_update_size(BinarySearchTree* self, PyObject* args) { + PyObject* start_idx; + + if (!PyArg_ParseTuple(args, "O", &start_idx)) { + return NULL; + } + + // Implement _update_size logic here + + Py_RETURN_NONE; +} + +// Method to insert a new node into the tree. +static PyObject* BinarySearchTree_insert(BinarySearchTree* self, PyObject* args) { + PyObject* key; + PyObject* data = NULL; + + if (!PyArg_ParseTuple(args, "O|O", &key, &data)) { + return NULL; + } + + // Implement insert logic here + + Py_RETURN_NONE; +} + +// Method to search for a key in the tree. +static PyObject* BinarySearchTree_search(BinarySearchTree* self, PyObject* args) { + PyObject* key; + + if (!PyArg_ParseTuple(args, "O", &key)) { + return NULL; + } + + // Implement search logic here + + Py_RETURN_NONE; +} + +// Method definitions for BinarySearchTree +static PyMethodDef BinarySearchTree_methods[] = { + {"_update_size", (PyCFunction)BinarySearchTree_update_size, METH_VARARGS, "Updates the size of nodes in the tree."}, + {"insert", (PyCFunction)BinarySearchTree_insert, METH_VARARGS, "Inserts a new node into the tree."}, + {"search", (PyCFunction)BinarySearchTree_search, METH_VARARGS, "Searches for a key in the tree."}, + {NULL} +}; + +// Type object for BinarySearchTree +static PyTypeObject BinarySearchTreeType = { + PyVarObject_HEAD_INIT(NULL, 0) + "BinarySearchTree", /* tp_name */ + sizeof(BinarySearchTree), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)BinarySearchTree_dealloc, /* tp_dealloc */ + 0, /* 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 */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + "BinarySearchTree objects", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + BinarySearchTree_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + BinarySearchTree_new, /* tp_new */ +}; + +// Module definition for the binarysearchtree module +static PyModuleDef binarysearchtreemodule = { + PyModuleDef_HEAD_INIT, + "binarysearchtree", // Module name + NULL, // Module documentation + -1, + NULL, NULL, NULL, NULL, NULL +}; + +// Module initialization function +PyMODINIT_FUNC PyInit_binarysearchtree(void) { + PyObject* m; + if (PyType_Ready(&BinarySearchTreeType) < 0) { + return NULL; + } + + m = PyModule_Create(&binarysearchtreemodule); + if (m == NULL) { + return NULL; + } + + Py_INCREF(&BinarySearchTreeType); + PyModule_AddObject(m, "BinarySearchTree", reinterpret_cast(&BinarySearchTreeType)); + + return m; +} diff --git a/pydatastructs/trees/_backend/cpp/binary_tree.cpp b/pydatastructs/trees/_backend/cpp/binary_tree.cpp new file mode 100644 index 000000000..b66e7e2fe --- /dev/null +++ b/pydatastructs/trees/_backend/cpp/binary_tree.cpp @@ -0,0 +1,196 @@ +#include +#include +#include + +// Define TreeNode struct. +// Defines a C struct TreeNode that represents a node in the binary tree. +// It contains pointers to data, left, and right. +typedef struct { + PyObject_HEAD + PyObject* data; + PyObject* left; + PyObject* right; +} TreeNode; + +// Define BinaryTree class. +// Defines a C struct BinaryTree that represents the binary tree. +// It contains members for root_idx, comparator, tree, size, and is_order_statistic. +typedef struct { + PyObject_VAR_HEAD + PyObject* root_idx; + PyObject* comparator; + PyObject* tree; + PyObject* size; + PyObject* is_order_statistic; +} BinaryTree; + +// Deallocation function for BinaryTree. +// Defines a deallocation function for BinaryTree. +// It releases the Python objects held by the BinaryTree instance and frees the memory. +static void BinaryTree_dealloc(BinaryTree* self) { + Py_XDECREF(self->root_idx); + Py_XDECREF(self->comparator); + Py_XDECREF(self->tree); + Py_XDECREF(self->size); + Py_XDECREF(self->is_order_statistic); + + Py_TYPE(self)->tp_free(reinterpret_cast(self)); +} + +// Object creation function for BinaryTree. +// Defines a new object creation function for BinaryTree. +// It allocates memory for a new instance, sets default values for members, and returns the new instance. +static PyObject* BinaryTree_new(PyTypeObject* type, PyObject* args, PyObject* kwds) { + BinaryTree* self; + self = reinterpret_cast(type->tp_alloc(type, 0)); + if (self != NULL) { + self->root_idx = PyLong_FromLong(0); + self->comparator = Py_None; + self->tree = PyList_New(0); + self->size = PyLong_FromLong(0); + self->is_order_statistic = Py_False; + } + return reinterpret_cast(self); +} + +// Initialization function for BinaryTree. +// Defines an initialization function for BinaryTree. +// This can be used to further initialize the object after creation if needed. +static int BinaryTree_init(BinaryTree* self, PyObject* args, PyObject* kwds) { + // Implement initialization logic here + return 0; +} + +// Insert method for BinaryTree. +static PyObject* BinaryTree_insert(BinaryTree* self, PyObject* args) { + PyObject* key; + PyObject* data = NULL; + + if (!PyArg_ParseTuple(args, "O|O", &key, &data)) { + return NULL; + } + + // Implement insert logic here + + Py_RETURN_NONE; +} + +// Delete method for BinaryTree +static PyObject* BinaryTree_delete(BinaryTree* self, PyObject* args) { + PyObject* key; + + if (!PyArg_ParseTuple(args, "O", &key)) { + return NULL; + } + + // Implement delete logic here + + Py_RETURN_NONE; +} + +// Search method for BinaryTree +static PyObject* BinaryTree_search(BinaryTree* self, PyObject* args) { + PyObject* key; + + if (!PyArg_ParseTuple(args, "O", &key)) { + return NULL; + } + + // Implement search logic here + + Py_RETURN_NONE; +} + +// String representation method for BinaryTree +static PyObject* BinaryTree_str(BinaryTree* self) { + // Implement __str__ logic here + return PyUnicode_FromString("BinaryTree Object"); +} + +// Method definitions for BinaryTree +static PyMethodDef BinaryTree_methods[] = { + {"insert", (PyCFunction)BinaryTree_insert, METH_VARARGS, "Inserts data into the binary tree."}, + {"delete", (PyCFunction)BinaryTree_delete, METH_VARARGS, "Deletes data from the binary tree."}, + {"search", (PyCFunction)BinaryTree_search, METH_VARARGS, "Searches for data in the binary tree."}, + {"__str__", (PyCFunction)BinaryTree_str, METH_NOARGS, "Returns the string representation of the binary tree."}, + {NULL} +}; + +// Member definitions for BinaryTree +static PyMemberDef BinaryTree_members[] = { + {"root_idx", T_OBJECT_EX, offsetof(BinaryTree, root_idx), 0, "Index of the root node"}, + {"comparator", T_OBJECT_EX, offsetof(BinaryTree, comparator), 0, "Comparator function"}, + {"tree", T_OBJECT_EX, offsetof(BinaryTree, tree), 0, "Binary tree structure"}, + {"size", T_OBJECT_EX, offsetof(BinaryTree, size), 0, "Size of the tree"}, + {"is_order_statistic", T_OBJECT_EX, offsetof(BinaryTree, is_order_statistic), 0, "Order statistic flag"}, + {NULL} +}; + +// Type object for BinaryTree +static PyTypeObject BinaryTreeType = { + PyVarObject_HEAD_INIT(NULL, 0) + "BinaryTree", /* tp_name */ + sizeof(BinaryTree), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)BinaryTree_dealloc, /* tp_dealloc */ + 0, /* 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 */ + (reprfunc)BinaryTree_str, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + "BinaryTree objects", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + BinaryTree_methods, /* tp_methods */ + BinaryTree_members, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)BinaryTree_init, /* tp_init */ + 0, /* tp_alloc */ + BinaryTree_new, /* tp_new */ +}; + +// Module definition for the binarytree module +static PyModuleDef binarytreemodule = { + PyModuleDef_HEAD_INIT, + "binarytree", // Module name + NULL, // Module documentation + -1, + NULL, NULL, NULL, NULL, NULL +}; + +// Module initialization function +PyMODINIT_FUNC PyInit_binarytree(void) { + PyObject* m; + if (PyType_Ready(&BinaryTreeType) < 0) { + return NULL; + } + + m = PyModule_Create(&binarytreemodule); + if (m == NULL) { + return NULL; + } + + Py_INCREF(&BinaryTreeType); + PyModule_AddObject(m, "BinaryTree", reinterpret_cast(&BinaryTreeType)); + + return m; +} diff --git a/pydatastructs/trees/_backend/cpp/tree_algorithms.cpp b/pydatastructs/trees/_backend/cpp/tree_algorithms.cpp new file mode 100644 index 000000000..bd93c6a06 --- /dev/null +++ b/pydatastructs/trees/_backend/cpp/tree_algorithms.cpp @@ -0,0 +1,31 @@ +#include +#include "trees.hpp" // Header file containing C++ implementations of wrapper functions of tree data structures + +// Method definitions +static PyMethodDef trees_PyMethodDef[] = { + {"binary_tree", (PyCFunction) binary_tree, METH_VARARGS, ""}, + // Add method definitions for other tree data structures over here. + {NULL, NULL, 0, NULL} /* Sentinel */ +}; + +// Sentinel info: +// The sentinel entry {NULL, NULL, 0, NULL} is used to indicate the end of the method definition array. +// When the Python interpreter processes this array, it stops iterating over the array when it encounters this sentinel entry. + +// Module structure +static struct PyModuleDef trees_module = { + PyModuleDef_HEAD_INIT, + "_trees", + NULL, + -1, + trees_PyMethodDef +}; + +// Module initialization function +PyMODINIT_FUNC PyInit__trees(void) { + PyObject *module; + module = PyModule_Create(&trees_module); + if (module == NULL) + return NULL; + return module; +} diff --git a/pydatastructs/trees/_extensions.py b/pydatastructs/trees/_extensions.py new file mode 100644 index 000000000..9c0e21d45 --- /dev/null +++ b/pydatastructs/trees/_extensions.py @@ -0,0 +1,24 @@ +from setuptools import Extension + +project = 'pydatastructs' + +module = 'trees' + +backend = '_backend' + +cpp = 'cpp' + +trees = '.'.join([project, module, backend, cpp, '_trees']) +trees_sources = ['/'.join([project, module, backend, cpp, + 'trees', 'trees.cpp'])] + +# Add tree algorithms later + +# algorithms = '.'.join([project, module, backend, cpp, '_algorithms']) +# algorithms_sources = ['/'.join([project, module, backend, cpp, +# 'algorithms', 'algorithms.cpp'])] + +extensions = [ + Extension(trees, sources=trees_sources), + # Extension(algorithms, sources=algorithms_sources) +]