Skip to content

Commit

Permalink
insert() for Cartesian Trees in C++ backend
Browse files Browse the repository at this point in the history
  • Loading branch information
Kishan-Ved committed Jul 10, 2024
1 parent 30ba890 commit 861e354
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 27 deletions.
2 changes: 1 addition & 1 deletion pydatastructs/trees/_backend/cpp/BinaryTree.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ static PyObject* BinaryTree___str__(BinaryTree *self) {
if (reinterpret_cast<PyObject*>(node) != Py_None) {
PyObject* out;
if (node->isCartesianTreeNode == true) {
out = Py_BuildValue("(OOOOO)", node->left, node->key, node->priority, node->data, node->right);
out = Py_BuildValue("(OOOOO)", node->left, node->key, PyLong_FromLong(node->priority), node->data, node->right);
}
else {
out = Py_BuildValue("(OOOO)", node->left, node->key, node->data, node->right);
Expand Down
35 changes: 34 additions & 1 deletion pydatastructs/trees/_backend/cpp/CartesianTree.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,42 @@ static PyObject* Cartesian_Tree__trickle_down(CartesianTree* self, PyObject *arg
Py_RETURN_NONE;
}

static PyObject* CartesianTree_insert(CartesianTree *self, PyObject* args) {
Py_INCREF(Py_None);
PyObject* key = Py_None;
Py_INCREF(Py_None);
PyObject* priority = Py_None;
Py_INCREF(Py_None);
PyObject* data = Py_None;
if (!PyArg_ParseTuple(args, "OO|O", &key, &priority, &data)) { // data is optional
return NULL;
}
BinaryTree* bt = self->sbbt->bst->binary_tree;

SelfBalancingBinaryTree_insert(self->sbbt, Py_BuildValue("(OO)", key, data));
PyObject* node_idx = SelfBalancingBinaryTree_search(self->sbbt, Py_BuildValue("(O)", key), PyDict_New());
TreeNode* node = reinterpret_cast<TreeNode*>(bt->tree->_one_dimensional_array->_data[PyLong_AsLong(node_idx)]);
if (PyType_Ready(&TreeNodeType) < 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;
}
TreeNode* new_node = reinterpret_cast<TreeNode*>(TreeNode___new__(&TreeNodeType, Py_BuildValue("(OO)", key, data), PyDict_New()));
new_node->isCartesianTreeNode = true;
new_node->priority = PyLong_AsLong(priority);
new_node->parent = node->parent;
new_node->left = node->left;
new_node->right = node->right;
bt->tree->_one_dimensional_array->_data[PyLong_AsLong(node_idx)] = reinterpret_cast<PyObject*>(new_node);
if (node->is_root) {
reinterpret_cast<TreeNode*>(bt->tree->_one_dimensional_array->_data[PyLong_AsLong(node_idx)])->is_root = true;
}
else {
Cartesian_Tree__bubble_up(self, Py_BuildValue("(O)", node_idx));
}
Py_RETURN_NONE;
}

static struct PyMethodDef CartesianTree_PyMethodDef[] = {
// {"insert", (PyCFunction) CartesianTree_insert, METH_VARARGS, NULL},
{"insert", (PyCFunction) CartesianTree_insert, METH_VARARGS, NULL},
// {"delete", (PyCFunction) CartesianTree_delete, METH_VARARGS | METH_KEYWORDS, NULL},
{"search", (PyCFunction) CartesianTree_search, METH_VARARGS | METH_KEYWORDS, NULL},
{NULL}
Expand Down
56 changes: 31 additions & 25 deletions pydatastructs/trees/tests/test_binary_trees.py
Original file line number Diff line number Diff line change
Expand Up @@ -410,8 +410,8 @@ def test_BinaryIndexedTree():
def test_cpp_BinaryIndexedTree():
_test_BinaryIndexedTree(Backend.CPP)

def test_CartesianTree():
tree = CartesianTree()
def _test_CartesianTree(backend):
tree = CartesianTree(backend=backend)
tree.insert(3, 1, 3)
tree.insert(1, 6, 1)
tree.insert(0, 9, 0)
Expand All @@ -430,31 +430,37 @@ def test_CartesianTree():
"(7, 7, 22, 7, 8), (None, 6, 42, 6, None), "
"(None, 8, 49, 8, None), (None, 2, 99, 2, None)]")

trav = BinaryTreeTraversal(tree)
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] == [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
assert [node.key for node in pre_order] == [3, 1, 0, 2, 5, 4, 9, 7, 6, 8]

tree.insert(1.5, 4, 1.5)
# trav = BinaryTreeTraversal(tree)
# 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] == [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
# assert [node.key for node in pre_order] == [3, 1, 0, 2, 5, 4, 9, 7, 6, 8]

# tree.insert(1.5, 4, 1.5)

# 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] == [0, 1, 1.5, 2, 3, 4, 5, 6, 7, 8, 9]
# assert [node.key for node in pre_order] == [3, 1.5, 1, 0, 2, 5, 4, 9, 7, 6, 8]

# k = tree.search(1.5)
# assert tree.tree[tree.tree[k].parent].key == 3
# tree.delete(1.5)
# tree.tree[tree.tree[tree.root_idx].left].key == 1
# tree.delete(8)
# assert tree.search(8) is None
# tree.delete(7)
# assert tree.search(7) is None
# tree.delete(3)
# assert tree.search(3) is None
# assert tree.delete(18) is None

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] == [0, 1, 1.5, 2, 3, 4, 5, 6, 7, 8, 9]
assert [node.key for node in pre_order] == [3, 1.5, 1, 0, 2, 5, 4, 9, 7, 6, 8]

k = tree.search(1.5)
assert tree.tree[tree.tree[k].parent].key == 3
tree.delete(1.5)
tree.tree[tree.tree[tree.root_idx].left].key == 1
tree.delete(8)
assert tree.search(8) is None
tree.delete(7)
assert tree.search(7) is None
tree.delete(3)
assert tree.search(3) is None
assert tree.delete(18) is None
def test_CartesianTree():
_test_CartesianTree(backend=Backend.PYTHON)

def test_cpp_CartesianTree():
_test_CartesianTree(backend=Backend.CPP)
test_cpp_CartesianTree()
def test_Treap():

random.seed(0)
Expand Down

0 comments on commit 861e354

Please sign in to comment.