From e4a9f543a0c6c1c2e56608ff8b85e54854ca457d Mon Sep 17 00:00:00 2001 From: kuntal0901 Date: Sat, 5 Oct 2024 18:40:46 +0530 Subject: [PATCH 1/5] feat: Implemented Morris Inorder traversal for Binary tree --- .../binary_tree/morris_inorder_traversal.py | 168 ++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 data_structures/binary_tree/morris_inorder_traversal.py diff --git a/data_structures/binary_tree/morris_inorder_traversal.py b/data_structures/binary_tree/morris_inorder_traversal.py new file mode 100644 index 000000000..c4aff076f --- /dev/null +++ b/data_structures/binary_tree/morris_inorder_traversal.py @@ -0,0 +1,168 @@ +""" +Problem Statement: Given a binary perform an inorder traversal using Morris Inorder +traversal algorithm. (Iterative version of Inorder traversal of tree) + +https://www.geeksforgeeks.org/inorder-tree-traversal-without-recursion-and-without-stack/ +""" + + +class TreeNode: + """ + Class representing a node in a binary tree. + + Attributes: + ----------- + value : int + The value stored at the node. + left : TreeNode + Pointer to the left child node (default is None). + right : TreeNode + Pointer to the right child node (default is None). + """ + + def __init__(self, value: int) -> None: + self.value = value + self.left: TreeNode | None = None + self.right: TreeNode | None = None + + +class BinaryTree: + """ + Class representing a binary tree. + + Methods: + -------- + insert(value: int) -> None: + Insert a value into the binary tree following binary search tree (BST) rules. + + morris_inorder_traversal() -> List[int]: + Perform inorder traversal and return list of node values. + + + >>> bt = BinaryTree() + >>> bt.insert(9) + >>> bt.insert(6) + >>> bt.insert(10) + >>> bt.insert(3) + >>> bt.insert(7) + >>> bt.insert(12) + >>> bt.insert(2) + >>> bt.insert(5) + >>> bt.insert(4) + >>> bt.morris_inorder_traversal() + [2, 3, 4, 5, 6, 7, 9, 10, 12] + + """ + + def __init__(self) -> None: + self.root: TreeNode | None = None + + def insert(self, value: int) -> None: + """ + Insert a value into the binary tree. + + Parameters: + ----------- + value : int + The value to be inserted into the binary tree. + """ + if self.root is None: + self.root = TreeNode(value) + else: + self._insert_recursive(self.root, value) + + def _insert_recursive(self, node: TreeNode, value: int) -> None: + """ + Helper function to insert a value recursively into the tree. + + Parameters: + ----------- + node : TreeNode + The current node in the binary tree. + value : int + The value to be inserted. + """ + if value < node.value: + if node.left is None: + node.left = TreeNode(value) + else: + self._insert_recursive(node.left, value) + elif node.right is None: + node.right = TreeNode(value) + else: + self._insert_recursive(node.right, value) + + def _predecessor(self, node: TreeNode) -> TreeNode: + """ + Helper Function to return predecessor of the given node in a binary tree + + Parameters: + ----------- + node : TreeNode + A node in the binary tree. + + Returns: + -------- + TreeNode: + The predecessor of the node passed in the parameter + """ + temp_node = node.left + while temp_node and temp_node.right and temp_node.right != node: + temp_node = temp_node.right + assert temp_node is not None, "Predecessor should not be None" + return temp_node + + def morris_inorder_traversal(self) -> list[int]: + """ + Function for inorder traversal using morris inorder traversal. + + Algorithm : + ------------ + First set current node as root node. + + while current node is not empty + If the current node has no left child. + print the current node. + point the current node to its right child + + else. + find predecssor node of the current node. + if predecessor has no right child, + make the current node as the right child of the predecessor node. + point current node to its left child. + else, + remove the link of the right child of predecessor node. + print the current node + point the current node to its right child. + + Returns: + -------- + List[int]: + A list of integers representing the inorder traversal. + + + + """ + inorder_traversal = [] + current_node = self.root + + while current_node: + if current_node.left is None: + inorder_traversal.append(current_node.value) + current_node = current_node.right + else: + predecessor_node = self._predecessor(current_node) + if predecessor_node.right is None: + predecessor_node.right = current_node + current_node = current_node.left + else: + predecessor_node.right = None + inorder_traversal.append(current_node.value) + current_node = current_node.right + return inorder_traversal + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From c6f14ee8609ddd5cf51bf9cf61fa2b6f382c6eba Mon Sep 17 00:00:00 2001 From: kuntal0901 Date: Sat, 5 Oct 2024 19:17:09 +0530 Subject: [PATCH 2/5] feat: Implemented Morris postorder traversal for Binary tree --- .../binary_tree/morris_postorder_traversal.py | 170 ++++++++++++++++++ 1 file changed, 170 insertions(+) create mode 100644 data_structures/binary_tree/morris_postorder_traversal.py diff --git a/data_structures/binary_tree/morris_postorder_traversal.py b/data_structures/binary_tree/morris_postorder_traversal.py new file mode 100644 index 000000000..b64173cc8 --- /dev/null +++ b/data_structures/binary_tree/morris_postorder_traversal.py @@ -0,0 +1,170 @@ +""" +Problem Statement: Given a binary perform an postorder traversal using Morris Postorder +traversal algorithm. (Iterative version of Postorder traversal of tree) + +https://www.geeksforgeeks.org/morris-traversal-for-postorder/ +""" + + +class TreeNode: + """ + Class representing a node in a binary tree. + + Attributes: + ----------- + value : int + The value stored at the node. + left : TreeNode + Pointer to the left child node (default is None). + right : TreeNode + Pointer to the right child node (default is None). + """ + + def __init__(self, value: int) -> None: + self.value = value + self.left: TreeNode | None = None + self.right: TreeNode | None = None + + +class BinaryTree: + """ + Class representing a binary tree. + + Methods: + -------- + insert(value: int) -> None: + Insert a value into the binary tree following binary search tree (BST) rules. + + morris_postorder_traversal() -> List[int]: + Perform postorder traversal and return list of node values. + + + >>> bt = BinaryTree() + >>> bt.insert(9) + >>> bt.insert(6) + >>> bt.insert(10) + >>> bt.insert(3) + >>> bt.insert(7) + >>> bt.insert(12) + >>> bt.insert(2) + >>> bt.insert(5) + >>> bt.insert(4) + >>> bt.morris_postorder_traversal() + [2, 4, 5, 3, 7, 6, 12, 10, 9] + + """ + + def __init__(self) -> None: + self.root: TreeNode | None = None + + def insert(self, value: int) -> None: + """ + Insert a value into the binary tree. + + Parameters: + ----------- + value : int + The value to be inserted into the binary tree. + """ + if self.root is None: + self.root = TreeNode(value) + else: + self._insert_recursive(self.root, value) + + def _insert_recursive(self, node: TreeNode, value: int) -> None: + """ + Helper function to insert a value recursively into the tree. + + Parameters: + ----------- + node : TreeNode + The current node in the binary tree. + value : int + The value to be inserted. + """ + if value < node.value: + if node.left is None: + node.left = TreeNode(value) + else: + self._insert_recursive(node.left, value) + elif node.right is None: + node.right = TreeNode(value) + else: + self._insert_recursive(node.right, value) + + def _successor(self, node: TreeNode) -> TreeNode: + """ + Helper Function to return successor of the given node in a binary tree + + Parameters: + ----------- + node : TreeNode + A node in the binary tree. + + Returns: + -------- + TreeNode: + The successor of the node passed in the parameter + """ + temp_node = node.right + while temp_node and temp_node.left and temp_node.left != node: + temp_node = temp_node.left + assert temp_node is not None, "Successor should not be None" + return temp_node + + def morris_postorder_traversal(self) -> list[int]: + """ + Function for postorder traversal using morris postorder traversal. + + Algorithm : + ------------ + First set current node as root node. + + while current node is not empty + If the current node has no right child. + push the current node to temp. + point the current node to its left child + + else. + find successor node of the current node. + if successor left child points to current node, + remove the link of the left child of successor node. + point the current node to its left child. + else, + push the current node to temp. + make the current node as the left child of the successor node. + point current node to its right child. + + Reverse the temp array to get postorder traversaol. + + Returns: + -------- + List[int]: + A list of integers representing the postorder traversal. + + + + """ + postorder_traversal = [] + current_node = self.root + + while current_node: + if current_node.right is None: + postorder_traversal.append(current_node.value) + current_node = current_node.left + else: + successor_node = self._successor(current_node) + if successor_node.left == current_node: + successor_node.left = current_node + current_node = current_node.left + else: + postorder_traversal.append(current_node.value) + successor_node.left = current_node + current_node = current_node.right + return postorder_traversal[::-1] + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From f08e77f6aa0555d11cb6d11e00ea9a6753657c8a Mon Sep 17 00:00:00 2001 From: kuntal0901 Date: Sat, 5 Oct 2024 19:19:06 +0530 Subject: [PATCH 3/5] deleting unecessary files --- .../binary_tree/morris_postorder_traversal.py | 170 ------------------ 1 file changed, 170 deletions(-) delete mode 100644 data_structures/binary_tree/morris_postorder_traversal.py diff --git a/data_structures/binary_tree/morris_postorder_traversal.py b/data_structures/binary_tree/morris_postorder_traversal.py deleted file mode 100644 index b64173cc8..000000000 --- a/data_structures/binary_tree/morris_postorder_traversal.py +++ /dev/null @@ -1,170 +0,0 @@ -""" -Problem Statement: Given a binary perform an postorder traversal using Morris Postorder -traversal algorithm. (Iterative version of Postorder traversal of tree) - -https://www.geeksforgeeks.org/morris-traversal-for-postorder/ -""" - - -class TreeNode: - """ - Class representing a node in a binary tree. - - Attributes: - ----------- - value : int - The value stored at the node. - left : TreeNode - Pointer to the left child node (default is None). - right : TreeNode - Pointer to the right child node (default is None). - """ - - def __init__(self, value: int) -> None: - self.value = value - self.left: TreeNode | None = None - self.right: TreeNode | None = None - - -class BinaryTree: - """ - Class representing a binary tree. - - Methods: - -------- - insert(value: int) -> None: - Insert a value into the binary tree following binary search tree (BST) rules. - - morris_postorder_traversal() -> List[int]: - Perform postorder traversal and return list of node values. - - - >>> bt = BinaryTree() - >>> bt.insert(9) - >>> bt.insert(6) - >>> bt.insert(10) - >>> bt.insert(3) - >>> bt.insert(7) - >>> bt.insert(12) - >>> bt.insert(2) - >>> bt.insert(5) - >>> bt.insert(4) - >>> bt.morris_postorder_traversal() - [2, 4, 5, 3, 7, 6, 12, 10, 9] - - """ - - def __init__(self) -> None: - self.root: TreeNode | None = None - - def insert(self, value: int) -> None: - """ - Insert a value into the binary tree. - - Parameters: - ----------- - value : int - The value to be inserted into the binary tree. - """ - if self.root is None: - self.root = TreeNode(value) - else: - self._insert_recursive(self.root, value) - - def _insert_recursive(self, node: TreeNode, value: int) -> None: - """ - Helper function to insert a value recursively into the tree. - - Parameters: - ----------- - node : TreeNode - The current node in the binary tree. - value : int - The value to be inserted. - """ - if value < node.value: - if node.left is None: - node.left = TreeNode(value) - else: - self._insert_recursive(node.left, value) - elif node.right is None: - node.right = TreeNode(value) - else: - self._insert_recursive(node.right, value) - - def _successor(self, node: TreeNode) -> TreeNode: - """ - Helper Function to return successor of the given node in a binary tree - - Parameters: - ----------- - node : TreeNode - A node in the binary tree. - - Returns: - -------- - TreeNode: - The successor of the node passed in the parameter - """ - temp_node = node.right - while temp_node and temp_node.left and temp_node.left != node: - temp_node = temp_node.left - assert temp_node is not None, "Successor should not be None" - return temp_node - - def morris_postorder_traversal(self) -> list[int]: - """ - Function for postorder traversal using morris postorder traversal. - - Algorithm : - ------------ - First set current node as root node. - - while current node is not empty - If the current node has no right child. - push the current node to temp. - point the current node to its left child - - else. - find successor node of the current node. - if successor left child points to current node, - remove the link of the left child of successor node. - point the current node to its left child. - else, - push the current node to temp. - make the current node as the left child of the successor node. - point current node to its right child. - - Reverse the temp array to get postorder traversaol. - - Returns: - -------- - List[int]: - A list of integers representing the postorder traversal. - - - - """ - postorder_traversal = [] - current_node = self.root - - while current_node: - if current_node.right is None: - postorder_traversal.append(current_node.value) - current_node = current_node.left - else: - successor_node = self._successor(current_node) - if successor_node.left == current_node: - successor_node.left = current_node - current_node = current_node.left - else: - postorder_traversal.append(current_node.value) - successor_node.left = current_node - current_node = current_node.right - return postorder_traversal[::-1] - - -if __name__ == "__main__": - import doctest - - doctest.testmod() From 31bc93f1a23c583869a241a9fab9b9e969d69a88 Mon Sep 17 00:00:00 2001 From: kuntal0901 Date: Sat, 5 Oct 2024 19:22:01 +0530 Subject: [PATCH 4/5] feat: Implemented Morris postorder traversal for Binary tree --- ...ersal.py => morris_postorder_traversal.py} | 76 ++++++++++--------- 1 file changed, 39 insertions(+), 37 deletions(-) rename data_structures/binary_tree/{morris_inorder_traversal.py => morris_postorder_traversal.py} (55%) diff --git a/data_structures/binary_tree/morris_inorder_traversal.py b/data_structures/binary_tree/morris_postorder_traversal.py similarity index 55% rename from data_structures/binary_tree/morris_inorder_traversal.py rename to data_structures/binary_tree/morris_postorder_traversal.py index c4aff076f..b64173cc8 100644 --- a/data_structures/binary_tree/morris_inorder_traversal.py +++ b/data_structures/binary_tree/morris_postorder_traversal.py @@ -1,8 +1,8 @@ """ -Problem Statement: Given a binary perform an inorder traversal using Morris Inorder -traversal algorithm. (Iterative version of Inorder traversal of tree) +Problem Statement: Given a binary perform an postorder traversal using Morris Postorder +traversal algorithm. (Iterative version of Postorder traversal of tree) -https://www.geeksforgeeks.org/inorder-tree-traversal-without-recursion-and-without-stack/ +https://www.geeksforgeeks.org/morris-traversal-for-postorder/ """ @@ -35,8 +35,8 @@ class BinaryTree: insert(value: int) -> None: Insert a value into the binary tree following binary search tree (BST) rules. - morris_inorder_traversal() -> List[int]: - Perform inorder traversal and return list of node values. + morris_postorder_traversal() -> List[int]: + Perform postorder traversal and return list of node values. >>> bt = BinaryTree() @@ -49,8 +49,8 @@ class BinaryTree: >>> bt.insert(2) >>> bt.insert(5) >>> bt.insert(4) - >>> bt.morris_inorder_traversal() - [2, 3, 4, 5, 6, 7, 9, 10, 12] + >>> bt.morris_postorder_traversal() + [2, 4, 5, 3, 7, 6, 12, 10, 9] """ @@ -92,9 +92,9 @@ class BinaryTree: else: self._insert_recursive(node.right, value) - def _predecessor(self, node: TreeNode) -> TreeNode: + def _successor(self, node: TreeNode) -> TreeNode: """ - Helper Function to return predecessor of the given node in a binary tree + Helper Function to return successor of the given node in a binary tree Parameters: ----------- @@ -104,62 +104,64 @@ class BinaryTree: Returns: -------- TreeNode: - The predecessor of the node passed in the parameter + The successor of the node passed in the parameter """ - temp_node = node.left - while temp_node and temp_node.right and temp_node.right != node: - temp_node = temp_node.right - assert temp_node is not None, "Predecessor should not be None" + temp_node = node.right + while temp_node and temp_node.left and temp_node.left != node: + temp_node = temp_node.left + assert temp_node is not None, "Successor should not be None" return temp_node - def morris_inorder_traversal(self) -> list[int]: + def morris_postorder_traversal(self) -> list[int]: """ - Function for inorder traversal using morris inorder traversal. + Function for postorder traversal using morris postorder traversal. Algorithm : ------------ First set current node as root node. while current node is not empty - If the current node has no left child. - print the current node. - point the current node to its right child + If the current node has no right child. + push the current node to temp. + point the current node to its left child else. - find predecssor node of the current node. - if predecessor has no right child, - make the current node as the right child of the predecessor node. - point current node to its left child. + find successor node of the current node. + if successor left child points to current node, + remove the link of the left child of successor node. + point the current node to its left child. else, - remove the link of the right child of predecessor node. - print the current node - point the current node to its right child. + push the current node to temp. + make the current node as the left child of the successor node. + point current node to its right child. + + Reverse the temp array to get postorder traversaol. Returns: -------- List[int]: - A list of integers representing the inorder traversal. + A list of integers representing the postorder traversal. """ - inorder_traversal = [] + postorder_traversal = [] current_node = self.root while current_node: - if current_node.left is None: - inorder_traversal.append(current_node.value) - current_node = current_node.right + if current_node.right is None: + postorder_traversal.append(current_node.value) + current_node = current_node.left else: - predecessor_node = self._predecessor(current_node) - if predecessor_node.right is None: - predecessor_node.right = current_node + successor_node = self._successor(current_node) + if successor_node.left == current_node: + successor_node.left = current_node current_node = current_node.left else: - predecessor_node.right = None - inorder_traversal.append(current_node.value) + postorder_traversal.append(current_node.value) + successor_node.left = current_node current_node = current_node.right - return inorder_traversal + return postorder_traversal[::-1] if __name__ == "__main__": From 7e010687c42da60a06b69d54ebaed1ebdc3a1685 Mon Sep 17 00:00:00 2001 From: kuntal0901 Date: Sat, 5 Oct 2024 23:44:30 +0530 Subject: [PATCH 5/5] fix: code review changes --- .../binary_tree/morris_postorder_traversal.py | 36 +++++-------------- 1 file changed, 9 insertions(+), 27 deletions(-) diff --git a/data_structures/binary_tree/morris_postorder_traversal.py b/data_structures/binary_tree/morris_postorder_traversal.py index b64173cc8..a9b354e4c 100644 --- a/data_structures/binary_tree/morris_postorder_traversal.py +++ b/data_structures/binary_tree/morris_postorder_traversal.py @@ -12,12 +12,9 @@ class TreeNode: Attributes: ----------- - value : int - The value stored at the node. - left : TreeNode - Pointer to the left child node (default is None). - right : TreeNode - Pointer to the right child node (default is None). + value : The value stored at the node. + left : Pointer to the left child node (default is None). + right : Pointer to the right child node (default is None). """ def __init__(self, value: int) -> None: @@ -30,15 +27,6 @@ class BinaryTree: """ Class representing a binary tree. - Methods: - -------- - insert(value: int) -> None: - Insert a value into the binary tree following binary search tree (BST) rules. - - morris_postorder_traversal() -> List[int]: - Perform postorder traversal and return list of node values. - - >>> bt = BinaryTree() >>> bt.insert(9) >>> bt.insert(6) @@ -63,8 +51,7 @@ class BinaryTree: Parameters: ----------- - value : int - The value to be inserted into the binary tree. + value : The value to be inserted into the binary tree. """ if self.root is None: self.root = TreeNode(value) @@ -77,10 +64,8 @@ class BinaryTree: Parameters: ----------- - node : TreeNode - The current node in the binary tree. - value : int - The value to be inserted. + node : The current node in the binary tree. + value : The value to be inserted. """ if value < node.value: if node.left is None: @@ -98,13 +83,11 @@ class BinaryTree: Parameters: ----------- - node : TreeNode - A node in the binary tree. + node : A node in the binary tree. Returns: -------- - TreeNode: - The successor of the node passed in the parameter + The successor of the node passed in the parameter """ temp_node = node.right while temp_node and temp_node.left and temp_node.left != node: @@ -139,8 +122,7 @@ class BinaryTree: Returns: -------- - List[int]: - A list of integers representing the postorder traversal. + A list of integers representing the postorder traversal.