Skip to content

Commit c6f14ee

Browse files
committed
feat: Implemented Morris postorder traversal for Binary tree
1 parent e4a9f54 commit c6f14ee

File tree

1 file changed

+170
-0
lines changed

1 file changed

+170
-0
lines changed
+170
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
"""
2+
Problem Statement: Given a binary perform an postorder traversal using Morris Postorder
3+
traversal algorithm. (Iterative version of Postorder traversal of tree)
4+
5+
https://www.geeksforgeeks.org/morris-traversal-for-postorder/
6+
"""
7+
8+
9+
class TreeNode:
10+
"""
11+
Class representing a node in a binary tree.
12+
13+
Attributes:
14+
-----------
15+
value : int
16+
The value stored at the node.
17+
left : TreeNode
18+
Pointer to the left child node (default is None).
19+
right : TreeNode
20+
Pointer to the right child node (default is None).
21+
"""
22+
23+
def __init__(self, value: int) -> None:
24+
self.value = value
25+
self.left: TreeNode | None = None
26+
self.right: TreeNode | None = None
27+
28+
29+
class BinaryTree:
30+
"""
31+
Class representing a binary tree.
32+
33+
Methods:
34+
--------
35+
insert(value: int) -> None:
36+
Insert a value into the binary tree following binary search tree (BST) rules.
37+
38+
morris_postorder_traversal() -> List[int]:
39+
Perform postorder traversal and return list of node values.
40+
41+
42+
>>> bt = BinaryTree()
43+
>>> bt.insert(9)
44+
>>> bt.insert(6)
45+
>>> bt.insert(10)
46+
>>> bt.insert(3)
47+
>>> bt.insert(7)
48+
>>> bt.insert(12)
49+
>>> bt.insert(2)
50+
>>> bt.insert(5)
51+
>>> bt.insert(4)
52+
>>> bt.morris_postorder_traversal()
53+
[2, 4, 5, 3, 7, 6, 12, 10, 9]
54+
55+
"""
56+
57+
def __init__(self) -> None:
58+
self.root: TreeNode | None = None
59+
60+
def insert(self, value: int) -> None:
61+
"""
62+
Insert a value into the binary tree.
63+
64+
Parameters:
65+
-----------
66+
value : int
67+
The value to be inserted into the binary tree.
68+
"""
69+
if self.root is None:
70+
self.root = TreeNode(value)
71+
else:
72+
self._insert_recursive(self.root, value)
73+
74+
def _insert_recursive(self, node: TreeNode, value: int) -> None:
75+
"""
76+
Helper function to insert a value recursively into the tree.
77+
78+
Parameters:
79+
-----------
80+
node : TreeNode
81+
The current node in the binary tree.
82+
value : int
83+
The value to be inserted.
84+
"""
85+
if value < node.value:
86+
if node.left is None:
87+
node.left = TreeNode(value)
88+
else:
89+
self._insert_recursive(node.left, value)
90+
elif node.right is None:
91+
node.right = TreeNode(value)
92+
else:
93+
self._insert_recursive(node.right, value)
94+
95+
def _successor(self, node: TreeNode) -> TreeNode:
96+
"""
97+
Helper Function to return successor of the given node in a binary tree
98+
99+
Parameters:
100+
-----------
101+
node : TreeNode
102+
A node in the binary tree.
103+
104+
Returns:
105+
--------
106+
TreeNode:
107+
The successor of the node passed in the parameter
108+
"""
109+
temp_node = node.right
110+
while temp_node and temp_node.left and temp_node.left != node:
111+
temp_node = temp_node.left
112+
assert temp_node is not None, "Successor should not be None"
113+
return temp_node
114+
115+
def morris_postorder_traversal(self) -> list[int]:
116+
"""
117+
Function for postorder traversal using morris postorder traversal.
118+
119+
Algorithm :
120+
------------
121+
First set current node as root node.
122+
123+
while current node is not empty
124+
If the current node has no right child.
125+
push the current node to temp.
126+
point the current node to its left child
127+
128+
else.
129+
find successor node of the current node.
130+
if successor left child points to current node,
131+
remove the link of the left child of successor node.
132+
point the current node to its left child.
133+
else,
134+
push the current node to temp.
135+
make the current node as the left child of the successor node.
136+
point current node to its right child.
137+
138+
Reverse the temp array to get postorder traversaol.
139+
140+
Returns:
141+
--------
142+
List[int]:
143+
A list of integers representing the postorder traversal.
144+
145+
146+
147+
"""
148+
postorder_traversal = []
149+
current_node = self.root
150+
151+
while current_node:
152+
if current_node.right is None:
153+
postorder_traversal.append(current_node.value)
154+
current_node = current_node.left
155+
else:
156+
successor_node = self._successor(current_node)
157+
if successor_node.left == current_node:
158+
successor_node.left = current_node
159+
current_node = current_node.left
160+
else:
161+
postorder_traversal.append(current_node.value)
162+
successor_node.left = current_node
163+
current_node = current_node.right
164+
return postorder_traversal[::-1]
165+
166+
167+
if __name__ == "__main__":
168+
import doctest
169+
170+
doctest.testmod()

0 commit comments

Comments
 (0)