chore(Python): Add Binary Tree Traversals both recursive and iterative method.

pull/1140/head
santhoshtk 2023-01-13 15:46:22 +05:30
parent af47764be0
commit b2a951dd65
2 changed files with 198 additions and 0 deletions

View File

@ -84,6 +84,7 @@
## Trees
- [Binary Tree](trees/binary_tree.py)
- [Binary Search Tree](trees/binary_search_tree.py)
- [Binary Tree Traversals](trees/binaryTreeTraversals.py)
## Queues
- [First in First out Queue](queues/fifo-queue.py)

View File

@ -0,0 +1,197 @@
"""
Data Structure : Binary Tree
Algorithm : Binary Tree Traversals (Pre-Order, In-Order, Post-Order)
Time Complexity : O(n)
Space Complexity: O(n) (Auxiliary space)
"""
from typing import Optional, Union
from queue import Queue, LifoQueue
from random import randint
class BinaryTreeNode:
"""
Class to represent Binary Tree Node.
Attributes:
- data (int) : The data stored in the `BinaryTreeNode`.
- leftChild (BinaryTreeNode) : The left child of the current node.
- rightChild (BinaryTreeNode) : The right child of the current node.
"""
def __init__(self, data: int) -> None:
self.data = data
self.leftChild: Optional[BinaryTreeNode] = None
self.rightChild: Optional[BinaryTreeNode] = None
class BinaryTree:
"""
Class to represent Binary Tree.
Attributes:
- root (BinaryTreeNode) : The root of the Binary Tree.
"""
def __init__(self):
self.root: Optional[BinaryTreeNode] = None
def insert(self, value: int) -> str:
"""
Create a `BinaryTreeNode` with the `value` and insert the node at the
vacant place in the Binary Tree.
NOTE : The vacant place can be found using level order traversal.
Also, we need queue for level order traversal.
:param value: The value of the `BinaryTreeNode`.
:return: A meaningful message to the user of the program.
"""
if not self.root:
self.root = BinaryTreeNode(value)
else:
# Creating the FIFO (Queue) for level order traversal
auxQueue = Queue()
auxQueue.put(self.root)
while not auxQueue.empty():
currentNode = auxQueue.get()
# Check if current node has vacant place.
if currentNode.leftChild is None:
currentNode.leftChild = BinaryTreeNode(value)
break
else:
auxQueue.put(currentNode.leftChild)
if currentNode.rightChild is None:
currentNode.rightChild = BinaryTreeNode(value)
break
else:
auxQueue.put(currentNode.rightChild)
return "The value inserted successfully in the Binary Tree."
class RecursiveTraversal:
"""Class to represent Recursive Traversals of the Binary Tree."""
def preOrder(self, root: BinaryTreeNode, result: list) -> Union[None, list]:
if not root:
return
else:
result.append(root.data)
self.preOrder(root.leftChild, result)
self.preOrder(root.rightChild, result)
return result
def inOrder(self, root: BinaryTreeNode, result: list) -> Union[None, list]:
if not root:
return
else:
self.inOrder(root.leftChild, result)
result.append(root.data)
self.inOrder(root.rightChild, result)
return result
def postOrder(self, root: BinaryTreeNode, result: list) -> Union[None, list]:
if not root:
return
else:
self.postOrder(root.leftChild, result)
self.postOrder(root.rightChild, result)
result.append(root.data)
return result
class IterativeTraversal(BinaryTree):
"""Class to represent Iterative Traversal for Binary Tree."""
def preOrder(self) -> Union[str, list]:
result = []
if not self.root:
return "The Binary Tree is Empty."
else:
auxStack = LifoQueue()
auxStack.put(self.root)
while not auxStack.empty():
currentNode = auxStack.get()
result.append(currentNode.data)
# Process right node then left node of the tree.
if currentNode.rightChild:
auxStack.put(currentNode.rightChild)
if currentNode.leftChild:
auxStack.put(currentNode.leftChild)
return result
def inOrder(self) -> Union[str, list]:
result = []
if not self.root:
return "The Binary Tree is Empty."
else:
auxStack = LifoQueue()
currentNode = self.root
while currentNode or not auxStack.empty():
# Process the left node
if currentNode:
auxStack.put(currentNode)
currentNode = currentNode.leftChild
else:
# Process the right node
currentNode = auxStack.get()
result.append(currentNode.data)
currentNode = currentNode.rightChild
return result
def postOrder(self) -> Union[str, list]:
result = []
if not self.root:
return "The Binary Tree is Empty."
else:
auxStack = []
previous: Optional[BinaryTreeNode] = None
currentNode = self.root
while currentNode or auxStack:
# Process the left node
while currentNode:
auxStack.append(currentNode)
currentNode = currentNode.leftChild
currentNode = auxStack[-1]
# Process the current node if it is the second visit.
if not currentNode.rightChild or previous == currentNode.rightChild:
previous = auxStack.pop()
result.append(previous.data)
currentNode = None
else:
currentNode = currentNode.rightChild
return result
if __name__ == "__main__":
bTree = IterativeTraversal()
# Create Binary Tree with random values
for _ in range(15):
bTree.insert(randint(0, 1000))
print("Iterative Outputs")
print(bTree.preOrder())
print(bTree.inOrder())
print(bTree.postOrder())
print("\nRecursive Outputs")
recursion = RecursiveTraversal()
print(recursion.preOrder(bTree.root, []))
print(recursion.inOrder(bTree.root, []))
print(recursion.postOrder(bTree.root, []))