Skip to content

Commit d7d935a

Browse files
committed
Morris Traversal for In-Order Traversal
1 parent eb5fab1 commit d7d935a

File tree

3 files changed

+75
-0
lines changed

3 files changed

+75
-0
lines changed

pydatastructs/trees/_backend/cpp/BinaryTreeTraversal.hpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,47 @@ static PyObject* BinaryTreeTraversal__out_order(BinaryTreeTraversal* self, PyObj
171171
return visit;
172172
}
173173

174+
static PyObject* BinaryTreeTraversal_morris_in_order(BinaryTreeTraversal* self, PyObject *args) {
175+
PyObject* node = NULL;
176+
if (!PyArg_ParseTuple(args, "|O", &node)) return NULL;
177+
178+
if (node == NULL) node = self->tree->root_idx;
179+
180+
PyObject* visit = PyList_New(0);
181+
ArrayForTrees* tree = self->tree->tree;
182+
PyObject* current = node;
183+
184+
if (current == Py_None || self->tree->size == 0) return visit;
185+
186+
while (current != Py_None) {
187+
TreeNode* curr_node = reinterpret_cast<TreeNode*>(tree->_one_dimensional_array->_data[PyLong_AsLong(current)]);
188+
189+
if (curr_node->left == Py_None) {
190+
PyList_Append(visit, reinterpret_cast<PyObject*>(curr_node));
191+
current = curr_node->right;
192+
} else {
193+
PyObject* pre_obj = curr_node->left;
194+
TreeNode* pre_node = reinterpret_cast<TreeNode*>(tree->_one_dimensional_array->_data[PyLong_AsLong(pre_obj)]);
195+
196+
while (pre_node->right != Py_None && pre_node->right != current) {
197+
pre_obj = pre_node->right;
198+
pre_node = reinterpret_cast<TreeNode*>(tree->_one_dimensional_array->_data[PyLong_AsLong(pre_obj)]);
199+
}
200+
201+
if (pre_node->right == Py_None) {
202+
pre_node->right = current;
203+
current = curr_node->left;
204+
} else {
205+
pre_node->right = Py_None;
206+
PyList_Append(visit, reinterpret_cast<PyObject*>(curr_node));
207+
current = curr_node->right;
208+
}
209+
}
210+
}
211+
212+
return visit;
213+
}
214+
174215
static PyObject* BinaryTreeTraversal_depth_first_search(BinaryTreeTraversal* self, PyObject *args, PyObject *kwds) {
175216
Py_INCREF(Py_None);
176217
PyObject* node = Py_None;
@@ -242,6 +283,7 @@ static struct PyMethodDef BinaryTreeTraversal_PyMethodDef[] = {
242283
{"_in_order", (PyCFunction) BinaryTreeTraversal__in_order, METH_VARARGS, NULL},
243284
{"_out_order", (PyCFunction) BinaryTreeTraversal__out_order, METH_VARARGS, NULL},
244285
{"_post_order", (PyCFunction) BinaryTreeTraversal__post_order, METH_VARARGS, NULL},
286+
{"morris_in_order", (PyCFunction) BinaryTreeTraversal_morris_in_order, METH_VARARGS, NULL},
245287
{"depth_first_search", (PyCFunction) BinaryTreeTraversal_depth_first_search, METH_VARARGS | METH_KEYWORDS, NULL},
246288
{"breadth_first_search", (PyCFunction) BinaryTreeTraversal_breadth_first_search, METH_VARARGS | METH_KEYWORDS, NULL},
247289
{NULL}

pydatastructs/trees/binary_trees.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1622,6 +1622,36 @@ def __new__(cls, tree, **kwargs):
16221622
obj.tree = tree
16231623
return obj
16241624

1625+
def morris_in_order(self, node=None):
1626+
"""
1627+
Implements Morris in-order traversal for the binary tree.
1628+
Returns
1629+
-------
1630+
list
1631+
The list of nodes in in-order.
1632+
"""
1633+
if node is None:
1634+
node = self.tree.root_idx
1635+
1636+
result = []
1637+
current = node
1638+
while current is not None:
1639+
if self.tree.tree[current].left is None:
1640+
result.append(self.tree.tree[current])
1641+
current = self.tree.tree[current].right
1642+
else:
1643+
predecessor = self.tree.tree[current].left
1644+
while (self.tree.tree[predecessor].right is not None and self.tree.tree[predecessor].right != current):
1645+
predecessor = self.tree.tree[predecessor].right
1646+
if self.tree.tree[predecessor].right is None:
1647+
self.tree.tree[predecessor].right = current
1648+
current = self.tree.tree[current].left
1649+
else:
1650+
self.tree.tree[predecessor].right = None
1651+
result.append(self.tree.tree[current])
1652+
current = self.tree.tree[current].right
1653+
return result
1654+
16251655
def _pre_order(self, node):
16261656
"""
16271657
Utility method for computing pre-order

pydatastructs/trees/tests/test_binary_trees.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,9 @@ def _test_BinaryTreeTraversal(backend):
142142
ino = trav.depth_first_search()
143143
assert [node.key for node in ino] == ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I']
144144

145+
morris_ino = trav.morris_in_order()
146+
assert [node.key for node in morris_ino] == ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I']
147+
145148
out = trav.depth_first_search(order='out_order')
146149
assert [node.key for node in out] == ['I', 'H', 'G', 'F', 'E', 'D', 'C', 'B', 'A']
147150

0 commit comments

Comments
 (0)