Trees_strategy Flashcards
/When we say two trees are identical?
what Data structure we use for iterative solution?
Two trees are identical id they have same contents and same structures
in iterative implementation we use stack = deque()
What is the time and space complexity in the algorithm for checking whether two trees are identical?
for both iterative and recursive, time complexity is O(n)
Space complexity in iterative is O(n) since we use stack
for recursive space complexity is proportional to the trees hight
Check if two binary trees are identical or not – Iterative
Algorithm:
1) check if x and y are both None –> return True
2) check if only x is None –> return False
3) check if only y is None –> return False
5) define stack = deque()
6) append a pair of (x,y)
7) while stack:
8) pop the top pair from stack
9) check if their key values are not equal, return False
10) check if they have left child: append the left child to the stack
11) elif x.left or y.left: retur False
12) do 10, 11 for right
code
from collections import deque
# A class to store a binary tree node class Node: def \_\_init\_\_(self, key=None, left=None, right=None): self.key = key self.left = left self.right = right
# Iterative function to check if two given binary trees are identical or not def isIdentical(x, y):
# if both trees are empty, return true if x is None and y is None: return True
# if the first tree is empty (and the second tree is non-empty), return false if x is None: return False
# if the second tree is empty (and the first tree is non-empty), return false if y is None: return False
# create a stack to hold pairs stack = deque() stack.append((x, y))
# loop till stack is empty while stack: # pop the top pair from the stack and process it x, y = stack.pop()
# if the value of their root node doesn't match, return false if x.key != y.key: return False
# if the left subtree of both `x` and `y` exists, push their addresses # to stack; otherwise, return false if only one left child exists if x.left and y.left: stack.append((x.left, y.left)) elif x.left or y.left: return False # if the right subtree of both `x` and `y` exists, push their addresses # to stack; otherwise, return false if only one right child exists if x.right and y.right: stack.append((x.right, y.right)) elif x.right or y.right: return False
# we reach here if both binary trees are identical return True
if __name__ == ‘__main__’:
# construct the first tree x = Node(15) x.left = Node(10) x.right = Node(20) x.left.left = Node(8) x.left.right = Node(12) x.right.left = Node(16) x.right.right = Node(25)
# construct the second tree y = Node(15) y.left = Node(10) y.right = Node(20) y.left.left = Node(8) y.left.right = Node(12) y.right.left = Node(16) y.right.right = Node(25)
if isIdentical(x, y): print('The given binary trees are identical') else: print('The given binary trees are not identical')from collections import deque
# A class to store a binary tree node class Node: def \_\_init\_\_(self, key=None, left=None, right=None): self.key = key self.left = left self.right = right
# Iterative function to check if two given binary trees are identical or not def isIdentical(x, y):
# if both trees are empty, return true if x is None and y is None: return True
# if the first tree is empty (and the second tree is non-empty), return false if x is None: return False
# if the second tree is empty (and the first tree is non-empty), return false if y is None: return False
# create a stack to hold pairs stack = deque() stack.append((x, y))
# loop till stack is empty while stack: # pop the top pair from the stack and process it x, y = stack.pop()
# if the value of their root node doesn't match, return false if x.key != y.key: return False
# if the left subtree of both `x` and `y` exists, push their addresses # to stack; otherwise, return false if only one left child exists if x.left and y.left: stack.append((x.left, y.left)) elif x.left or y.left: return False # if the right subtree of both `x` and `y` exists, push their addresses # to stack; otherwise, return false if only one right child exists if x.right and y.right: stack.append((x.right, y.right)) elif x.right or y.right: return False
# we reach here if both binary trees are identical return True
if __name__ == ‘__main__’:
# construct the first tree x = Node(15) x.left = Node(10) x.right = Node(20) x.left.left = Node(8) x.left.right = Node(12) x.right.left = Node(16) x.right.right = Node(25)
# construct the second tree y = Node(15) y.left = Node(10) y.right = Node(20) y.left.left = Node(8) y.left.right = Node(12) y.right.left = Node(16) y.right.right = Node(25)
if isIdentical(x, y): print('The given binary trees are identical') else: print('The given binary trees are not identical')
Check if two binary trees are identical or not Recursive
Write an efficient algorithm to check if two binary trees are identical or not. Two binary trees are identical if they have identical structure and their contents are also the same.
Algorithm :
1) if both trees are empty, return true
2) if both tree are not empty, and their keys are equal , recur function for x.left , y.left, x.right, y.righ
code
# A class to store a binary tree node class Node: def \_\_init\_\_(self, key=None, left=None, right=None): self.key = key self.left = left self.right = right
# Recursive function to check if two given binary trees are identical or not def isIdentical(x, y):
# if both trees are empty, return true if x is None and y is None: return True
# if both trees are non-empty and the value of their root node matches, # recur for their left and right subtree return (x is not None and y is not None) and (x.key == y.key) and \ isIdentical(x.left, y.left) and isIdentical(x.right, y.right)
if __name__ == ‘__main__’:
# construct the first tree x = Node(15) x.left = Node(10) x.right = Node(20) x.left.left = Node(8) x.left.right = Node(12) x.right.left = Node(16) x.right.right = Node(25)
# construct the second tree y = Node(15) y.left = Node(10) y.right = Node(20) y.left.left = Node(8) y.left.right = Node(12) y.right.left = Node(16) y.right.right = Node(25)
if isIdentical(x, y): print('The given binary trees are identical') else: print('The given binary trees are not identical')
1) 2 types of Tree traversal
2) 2 types of traversal algorithm implementations
1) depth-first search ( going down the tree)
pre order, post order, inorder
breath first search tree –> level order traversal
2) algorithms could be implemented is recursion manner where data stored in the call stack
or in iterative order where the data stored in the stacks
implement post order tree traversal in recursive
For traversing a (non-empty) binary tree in a postorder fashion, we must do these three things for every node n starting from the tree’s root:
(L) Recursively traverse its left subtree. When this step is finished, we are back at n again.
(R) Recursively traverse its right subtree. When this step is finished, we are back at n again.
(N) Process n itself.
As we can see, before processing any node, the left subtree is processed first, followed by the right subtree, and the node is processed at last. These operations can be defined recursively for each node. The recursive implementation is referred to as a Depth–first search (DFS), as the search tree is deepened as much as possible on each child before going to the next sibling.
________ code________
# Data structure to store a binary tree node class Node: def \_\_init\_\_(self, data=None, left=None, right=None): self.data = data self.left = left self.right = right
# Recursive function to perform postorder traversal on the tree def postorder(root):
# return if the current node is empty if root is None: return
# Traverse the left subtree postorder(root.left)
# Traverse the right subtree postorder(root.right)
# Display the data part of the root (or current node) print(root.data, end=' ')
if __name__ == ‘__main__’:
''' Construct the following tree 1 / \ / \ 2 3 / / \ / / \ 4 5 6 / \ / \ 7 8 '''
root = Node(1) root. left = Node(2) root. right = Node(3) root. left.left = Node(4) root. right.left = Node(5) root. right.right = Node(6) root. right.left.left = Node(7) root. right.left.right = Node(8) postorder(root)
Post order tree traversal, iterative
iterativePostorder(node)
s —> empty stack t —> output stack while (not s.isEmpty()) node —> s.pop() t.push(node)
if (node.left <> null)
s.push(node.left)
if (node.right <> null)
s.push(node.right)
while (not t.isEmpty())
node —> t.pop()
visit(node)
https://www.techiedelight.com/postorder-tree-traversal-iterative-recursive/
________ code
from collections import deque
# Data structure to store a binary tree node class Node: def \_\_init\_\_(self, data=None, left=None, right=None): self.data = data self.left = left self.right = right
# Iterative function to perform postorder traversal on the tree def postorderIterative(root):
# return if the tree is empty if root is None: return
# create an empty stack and push the root node stack = deque() stack.append(root)
# create another stack to store postorder traversal out = deque()
# loop till stack is empty while stack:
# pop a node from the stack and push the data into the output stack curr = stack.pop() out.append(curr.data)
# push the left and right child of the popped node into the stack if curr.left: stack.append(curr.left) if curr.right: stack.append(curr.right)
# print postorder traversal while out: print(out.pop(), end=' ')
if __name__ == ‘__main__’:
''' Construct the following tree 1 / \ / \ 2 3 / / \ / / \ 4 5 6 / \ / \ 7 8 '''
root = Node(1) root. left = Node(2) root. right = Node(3) root. left.left = Node(4) root. right.left = Node(5) root. right.right = Node(6) root. right.left.left = Node(7) root. right.left.right = Node(8) postorderIterative(root)
In-order tree traversal recurssion
# Data structure to store a binary tree node class Node: def \_\_init\_\_(self, data=None, left=None, right=None): self.data = data self.left = left self.right = right
# Recursive function to perform inorder traversal on the tree def inorder(root):
# return if the current node is empty if root is None: return
# Traverse the left subtree inorder(root.left)
# Display the data part of the root (or current node) print(root.data, end=' ')
# Traverse the right subtree inorder(root.right)
if __name__ == ‘__main__’:
''' Construct the following tree 1 / \ / \ 2 3 / / \ / / \ 4 5 6 / \ / \ 7 8 '''
root = Node(1) root. left = Node(2) root. right = Node(3) root. left.left = Node(4) root. right.left = Node(5) root. right.right = Node(6) root. right.left.left = Node(7) root. right.left.right = Node(8) inorder(root)
Inorder traversal itteratively
iterativeInorder(node)
s —> empty stack while (not s.isEmpty() or node != null) if (node != null) s.push(node) node —> node.left else node —> s.pop() visit(node) node —> node.right
code############
from collections import deque
# Data structure to store a binary tree node class Node: def \_\_init\_\_(self, data=None, left=None, right=None): self.data = data self.left = left self.right = right
# Iterative function to perform inorder traversal on the tree def inorderIterative(root):
# create an empty stack stack = deque()
# start from the root node (set current node to the root node) curr = root
# if the current node is None and the stack is also empty, we are done while stack or curr:
# if the current node exists, push it into the stack (defer it) # and move to its left child if curr: stack.append(curr) curr = curr.left else: # otherwise, if the current node is None, pop an element from the stack, # print it, and finally set the current node to its right child curr = stack.pop() print(curr.data, end=' ') curr = curr.right
if __name__ == ‘__main__’:
''' Construct the following tree 1 / \ / \ 2 3 / / \ / / \ 4 5 6 / \ / \ 7 8 '''
root = Node(1) root. left = Node(2) root. right = Node(3) root. left.left = Node(4) root. right.left = Node(5) root. right.right = Node(6) root. right.left.left = Node(7) root. right.left.right = Node(8) inorderIterative(root)
Pre-order traversal of Tree recurssion
As we can see, only after processing any node, the left subtree is processed, followed by the right subtree. These operations can be defined recursively for each node. The recursive implementation is referred to as a Depth–first search (DFS), as the search tree is deepened as much as possible on each child before going to the next sibling.
# Data structure to store a binary tree node class Node: def \_\_init\_\_(self, data=None, left=None, right=None): self.data = data self.left = left self.right = right
# Recursive function to perform preorder traversal on the tree def preorder(root):
# return if the current node is empty if root is None: return
# Display the data part of the root (or current node) print(root.data, end=' ')
# Traverse the left subtree preorder(root.left)
# Traverse the right subtree preorder(root.right)
if __name__ == ‘__main__’:
''' Construct the following tree 1 / \ / \ 2 3 / / \ / / \ 4 5 6 / \ / \ 7 8 '''
root = Node(1) root. left = Node(2) root. right = Node(3) root. left.left = Node(4) root. right.left = Node(5) root. right.right = Node(6) root. right.left.left = Node(7) root. right.left.right = Node(8) preorder(root)
Pre-order iteratively
iterativePreorder(node)
if (node = null) return s —> empty stack s.push(node) while (not s.isEmpty()) node —> s.pop() visit(node) if (node.right != null) s.push(node.right) if (node.left != null) s.push(node.left)
################# code from collections import deque
# Data structure to store a binary tree node class Node: def \_\_init\_\_(self, data=None, left=None, right=None): self.data = data self.left = left self.right = right
# Iterative function to perform preorder traversal on the tree def preorderIterative(root):
# return if the tree is empty if root is None: return
# create an empty stack and push the root node stack = deque() stack.append(root)
# loop till stack is empty while stack:
# pop a node from the stack and print it curr = stack.pop()
print(curr.data, end=' ') # push the right child of the popped node into the stack if curr.right: stack.append(curr.right) # push the left child of the popped node into the stack if curr.left: stack.append(curr.left)
# the right child must be pushed first so that the left child # is processed first (LIFO order)
if __name__ == ‘__main__’:
''' Construct the following tree 1 / \ / \ 2 3 / / \ / / \ 4 5 6 / \ / \ 7 8 '''
root = Node(1) root. left = Node(2) root. right = Node(3) root. left.left = Node(4) root. right.left = Node(5) root. right.right = Node(6) root. right.left.left = Node(7) root. right.left.right = Node(8) preorderIterative(root)
Calculate the height of a binary tree recursive
# A class to store a binary tree node class Node: def \_\_init\_\_(self, key=None, left=None, right=None): self.key = key self.left = left self.right = right
# Recursive function to calculate the height of a given binary tree def height(root):
# base case: empty tree has a height of 0 if root is None: return 0
# recur for the left and right subtree and consider maximum depth return 1 + max(height(root.left), height(root.right))
if __name__ == ‘__main__’:
root = Node(15) root. left = Node(10) root. right = Node(20) root. left.left = Node(8) root. left.right = Node(12) root. right.left = Node(16) root. right.right = Node(25) print('The height of the binary tree is', height(root))
Calculate the height of a binary tree itterative
The idea is to traverse the tree in a postorder fashion and calculate the height of the left and right subtree. The height of a subtree rooted at any node will be one more than the maximum height of its left and right subtree. Recursively apply this property to all tree nodes in a bottom-up manner (postorder fashion) and return the subtree’s maximum height rooted at that node. ###### code#################
def deleteTree(root): if root: # delete left subtree deleteTree(root.leftChild) # delete right subtree deleteTree(root.rightChild) # traverse root print("Deleting Node:", root.data) del root
from collections import deque
# A class to store a binary tree node class Node: def \_\_init\_\_(self, data, left=None, right=None): self.key = data self.left = left self.right = right
# Iterative function to calculate the height of a given binary tree # by doing level order traversal on the tree def height(root):
# empty tree has a height of 0 if root is None: return 0
# create an empty queue and enqueue the root node queue = deque() queue.append(root)
height = 0
# loop till queue is empty while queue:
# calculate the total number of nodes at the current level size = len(queue)
# process each node of the current level and enqueue their # non-empty left and right child while size > 0: front = queue.popleft()
if front.left: queue.append(front.left) if front.right: queue.append(front.right) size = size - 1
# increment height by 1 for each level height = height + 1
return height
Claculate the height of a binary tree, itteratively
We need to traverse by level order of a tree and calculate the tree level.
then need to modify Breadth First Search:
algorith: - if root is None -> return0 - q --> empty queu() - q.enqueue(root) - hight = 0 - while not q.isEmpty() size -> len(stack) while size: front -> stack.popleft() if front.left --> stack.enqueueu(front.left) f front.right --> stack.enqueueu(front.right)
hight+1
from collections import deque
# A class to store a binary tree node class Node: def \_\_init\_\_(self, data, left=None, right=None): self.key = data self.left = left self.right = right
# Iterative function to calculate the height of a given binary tree # by doing level order traversal on the tree def height(root):
# empty tree has a height of 0 if root is None: return 0
# create an empty queue and enqueue the root node queue = deque() queue.append(root)
height = 0
# loop till queue is empty while queue:
# calculate the total number of nodes at the current level size = len(queue)
# process each node of the current level and enqueue their # non-empty left and right child while size > 0: front = queue.popleft()
if front.left: queue.append(front.left) if front.right: queue.append(front.right) size = size - 1
# increment height by 1 for each level height = height + 1
return height
Breadth First serch - level order traversal in recurssion
A simple solution is to print all nodes of level 1 first, followed by level 2, until level h, where h is the tree’s height. We can print all nodes present in a level by modifying the preorder traversal on the tree.
The time complexity of the above solution is O(n2), where n is the total number of nodes in the binary tree. The auxiliary space required by the program is O(h) for the call stack, where h is the height of the tree
############# code######### # A class to store a binary tree node class Node: def \_\_init\_\_(self, key=None, left=None, right=None): self.key = key self.left = left self.right = right
# Function to print all nodes of a given level from left to right def printLevel(root, level):
# base case if root is None: return False
if level == 1: print(root.key, end=' ')
# return true if at least one node is present at a given level return True
left = printLevel(root.left, level - 1) right = printLevel(root.right, level - 1) return left or right
# Function to print level order traversal of a given binary tree def levelOrderTraversal(root):
# start from level 1 — till the height of the tree level = 1
# run till printLevel() returns false while printLevel(root, level): level = level + 1
if __name__ == ‘__main__’:
root = Node(15) root. left = Node(10) root. right = Node(20) root. left.left = Node(8) root. left.right = Node(12) root. right.left = Node(16) root. right.right = Node(25) levelOrderTraversal(root)
Breadth -First- Serach, iteratively
We can reduce the time complexity to O(n) by using extra space. Following is a pseudocode for a simple queue-based level order traversal, which requires space proportional to the maximum number of nodes at a given depth. It can be as much as half the total number of nodes.
levelorder(root) q —> empty queue q.enqueue(root) while (not q.isEmpty()) node —> q.dequeue() visit(node) if (node.left <> null) q.enqueue(node.left) if (node.right <> null) q.enqueue(node.right) #######################code############
from collections import deque
# A class to store a binary tree node class Node: def \_\_init\_\_(self, key=None, left=None, right=None): self.key = key self.left = left self.right = right
# Function to print level order traversal of a given binary tree def levelOrderTraversal(root):
# base case if not root: return
# create an empty queue and enqueue the root node queue = deque() queue.append(root)
# loop till queue is empty while queue:
# process each node in the queue and enqueue their # non-empty left and right child curr = queue.popleft()
print(curr.key, end=' ') if curr.left: queue.append(curr.left) if curr.right: queue.append(curr.right)
if __name__ == ‘__main__’:
root = Node(15) root. left = Node(10) root. right = Node(20) root. left.left = Node(8) root. left.right = Node(12) root. right.left = Node(16) root. right.right = Node(25) levelOrderTraversal(root)
Level order traversal (BDS) of a tree using multimap :)
Very Very Important
# A class to store a binary tree node class Node: def \_\_init\_\_(self, key=None, left=None, right=None): self.key = key self.left = left self.right = right
# Traverse the tree in a preorder fashion and store nodes in a dictionary # corresponding to their level def preorder(root, level, d):
# base case: empty tree if root is None: return
# insert the current node and its level into the dictionary d.setdefault(level, []).append(root.key)
# recur for the left and right subtree by increasing the level by 1 preorder(root.left, level + 1, d) preorder(root.right, level + 1, d)
# Recursive function to print level order traversal of a given binary tree def levelOrderTraversal(root):
# create an empty dictionary to store nodes between given levels d = {}
# traverse the tree and insert its nodes into the dictionary # corresponding to their level preorder(root, 1, d)
# iterate through the dictionary and print all nodes between given levels for i in range(1, len(d) + 1): print(f'Level {i}:', d[i])
if __name__ == ‘__main__’:
root = Node(15) root. left = Node(10) root. right = Node(20) root. left.left = Node(8) root. left.right = Node(12) root. right.left = Node(16) root. right.right = Node(25) root. right.right.right = Node(30) levelOrderTraversal(root)
Spiral order traversal of a binary tree – iteratively
Given a binary tree, print its nodes level by level in spiral order, i.e., all nodes present at level 1 should be printed first from left to right, followed by nodes of level 2 from right to left, followed by nodes of level 3 from left to right and so on… In other words, odd levels should be printed from left to right, and even levels should be printed from right to left or vice versa.
For example, the spiral level order traversal for the following tree is
(1, 3, 2, 4, 5, 6, 7) or (1, 2, 3, 7, 6, 5, 4)
The time complexity of the above solution is O(n2), where n is the total number of nodes in the binary tree.
We can reduce the time complexity to O(n) by using extra space. Following is a pseudocode for a simple queue-based spiral order traversal:
levelorder(root) q —> empty double ended queue q.push(root) while (not q.isEmpty()) while (level is even) node —> q.popFront() visit(node) if (node.left <> null) q.pushBack(node.left) if (node.right <> null) q.pushBack(node.right)
while (level is odd) node —> q.popBack() visit(node) if (node.right <> null) q.pushFront(node.right) if (node.left <> null) q.pushFront(node.left)
https://www.techiedelight.com/spiral-order-traversal-binary-tree/
code##############
from collections import deque
# A class to store a binary tree node class Node: def \_\_init\_\_(self, key=None, left=None, right=None): self.key = key self.left = left self.right = right
# Function to print spiral order traversal of a given binary tree def spiralOrderTraversal(root):
if root is None: return
# create an empty double-ended queue and enqueue the root node q = deque() # or use deque q.appendleft(root)
# `flag` is used to differentiate between odd or even level flag = True
# loop till deque is empty while q:
# calculate the total number of nodes at the current level nodeCount = len(q)
# print left to right if flag: # process each node of the current level and enqueue their # non-empty left and right child to deque while nodeCount > 0: # pop from the front if `flag` is true curr = q.popleft() print(curr.key, end=' ')
# it is important to push the left child into the back, # followed by the right child
if curr.left: q.append(curr.left) if curr.right: q.append(curr.right) nodeCount = nodeCount - 1
# print right to left else: # process each node of the current level and enqueue their # non-empty right and left child while nodeCount > 0: # it is important to pop from the back curr = q.pop() print(curr.key, end=' ') # print front node
# it is important to push the right child at the front, # followed by the left child
if curr.right: q.appendleft(curr.right) if curr.left: q.appendleft(curr.left) nodeCount = nodeCount - 1
# flip the flag for the next level flag = not flag print()
if __name__ == ‘__main__’:
root = Node(15) root. left = Node(10) root. right = Node(20) root. left.left = Node(8) root. left.right = Node(12) root. right.left = Node(16) root. right.right = Node(25) spiralOrderTraversal(root)
Spiral order traversal of a binary tree – using multimap
Given a binary tree, print its nodes level by level in spiral order, i.e., all nodes present at level 1 should be printed first from left to right, followed by nodes of level 2 from right to left, followed by nodes of level 3 from left to right and so on… In other words, odd levels should be printed from left to right, and even levels should be printed from right to left or vice versa.
For example, the spiral level order traversal for the following tree is
We can also solve this problem by using hashing. The following code traverses the tree in a preorder fashion and uses a map to store every node and its level using the level number as a key.
The time complexity of the above solution is O(n) and requires O(n) extra space, where n is the size of the binary tree.
code ###########
from collections import deque
# A class to store a binary tree node class Node: def \_\_init\_\_(self, key=None, left=None, right=None): self.key = key self.left = left self.right = right
# Traverse the tree in a preorder fashion and store nodes in a dictionary # corresponding to their level def preorder(root, level, d):
# base case: empty tree if root is None: return
# insert the current node and its level into the dictionary # if the level is odd, insert at the back; otherwise, search at front if level % 2 == 1: d.setdefault(level, deque()).append(root.key) else: d.setdefault(level, deque()).appendleft(root.key) # recur for the left and right subtree by increasing the level by 1 preorder(root.left, level + 1, d) preorder(root.right, level + 1, d)
# Recursive function to print spiral order traversal of a given binary tree def levelOrderTraversal(root):
# create an empty dictionary to store nodes between given levels d = {}
# traverse the tree and insert its nodes into the dictionary # corresponding to their level preorder(root, 1, d)
# iterate through the dictionary and print all nodes present at every level for i in range(1, len(d) + 1): print(f'Level {i}:', list(d[i]))
if __name__ == ‘__main__’:
root = Node(15) root. left = Node(10) root. right = Node(20) root. left.left = Node(8) root. left.right = Node(12) root. right.left = Node(16) root. right.right = Node(25) root. left.left.left = Node(20) root. right.right.right = Node(30) levelOrderTraversal(root)
Reverse level order traversal of a binary tree — iterattively
Given a binary tree, print its nodes level by level in reverse order, i.e., print all nodes present at the last level first, followed by nodes of the second last level, and so on… Print nodes at any level from left to right.
levelorder(root)
q —> empty queue s —> empty stack q.enqueue(root) while (not q.isEmpty()) node —> q.dequeue() s.push(node) if (node.right <> null) q.enqueue(node.right) if (node.left <> null) q.enqueue(node.left)
while (not s.isEmpty())
node —> s.pop()
print(node)
time and space : O(n) https://www.techiedelight.com/reverse-level-order-traversal-binary-tree/ ########## code##########
from collections import deque
# A class to store a binary tree node class Node: def \_\_init\_\_(self, key=None, left=None, right=None): self.key = key self.left = left self.right = right
# Function to print reverse level order traversal of a given binary tree def reverseLevelOrderTraversal(root):
if root is None: return
# create an empty queue and enqueue the root node queue = deque() queue.append(root)
# create a stack to reverse level order nodes stack = deque()
# loop till queue is empty while queue:
# process each node in the queue and enqueue their children curr = queue.popleft()
# push the current node into the stack stack.append(curr.key)
# it is important to process the right node before the left node if curr.right: queue.append(curr.right) if curr.left: queue.append(curr.left)
# pop all nodes from the stack and print them while stack: print(stack.pop(), end=' ')
if __name__ == ‘__main__’:
root = Node(15) root. left = Node(10) root. right = Node(20) root. left.left = Node(8) root. left.right = Node(12) root. right.left = Node(16) root. right.right = Node(25) reverseLevelOrderTraversal(root)