Lowest Common Ancestor in Binary Tree using recursion - python

I am trying to implement the solution to the problem Lowest Common Ancestor(LCA) of Binary Tree via top-down recursion.
The approach I have used is:
IDEA: Find the node which has one of the desired nodes in either subtree while the other desired node is the opposite subtree.
PSEUDOCODE
1. If the value of root is equal to either of the desired node's value,
the root is the LCA.
2. Search in the left subtree for either node.
3. Search in the right subtree for either node.
4. If neither of them contains any of the two nodes,
the nodes do not exist in the tree rooted at the root node.
5. If each of them contains one node,
the root is the LCA.
6. If either one of them contains a node,
return it to the root.
This is what has also been recommended in answers of related questions on StackOverflow.
Now, this code works well if we assume all the nodes of the tree to be of unique value. In other words, this approach seems to break in case of duplicates (or, is it just my implementation?)
I would like to know how can I fix my code to work with duplicate values as well. If this approach cannot result in the optimal solution, how should I alter my approach?
Here is the exact implementation:
class TreeNode(object):
def __init__(self, x):
self.val = x
self.left = None
self.right = None
def __repr__(self):
return 'TreeNode({}, {}, {})'.format(self.val, self.left, self.right)
def lowestCommonAncestor(root, p, q):
"""
:type root: TreeNode
:type p: TreeNode
:type q: TreeNode
:rtype: TreeNode
"""
if root is None:
return None
if p.val == root.val or q.val == root.val:
return root
left_subtree = lowestCommonAncestor(root.left, p, q)
right_subtree = lowestCommonAncestor(root.right, p, q)
if left_subtree is None and right_subtree is None:
return None
if left_subtree is not None and right_subtree is not None:
return root
if left_subtree is None:
return right_subtree
else:
return left_subtree
For example:
root = TreeNode(2)
root.left = TreeNode(3)
root.left.left = TreeNode(1)
root.right = TreeNode(5)
root.right.left = TreeNode(7)
root.right.right = TreeNode(1)
print(lowestCommonAncestor(root, TreeNode(1), TreeNode(7)))
This returns the root of the tree as the result.
result = TreeNode(2)
No doubt, the root is always an ancestor.
However, there exists a "lower" common ancestor than the root - TreeNode(5).

You have some problems:
1) Why are you checking for Node.val? You should be able to just compare one Node with another Node directly. That should solve issues when you have a tree with multiple nodes which have the same value... assuming that is your only problem.
2) Why do you return root if the left subtree is non-empty and the right subtree is non-empty? In many cases, of course, that will return root. This is generally not the behavior we want.
You may want to rethink your algorithm from scratch (you have some nice ideas going, but now that you see you've made some mistakes and since this problem is fairly simple/straightforward, it might be more beneficial to think afresh).
A suggestion: since this problem is a problem on trees, and has to do with search/paths, consider the problem of finding a path from Node p to Node q. We know that in a tree, there exists exactly one path from any two nodes (this simply follows from the fact that a tree is a connected acyclic graph, by definition).
You might keep this idea in mind when going back up after recursing to a base case, or after recursing to a base case you might want to create a data structure to store visited nodes in a loop then test some conditions and maybe recurse more (essentially a DFS approach vs a BFS approach, while the BFS approach uses explicit memoization / added memory, whereas DFS uses the stack to remember things).

The code will look like this
def lowestCommonAncestor(root, p, q):
"""
:type root: TreeNode
:type p: TreeNode
:type q: TreeNode
:rtype: TreeNode
"""
flag=0
if root is None:
return None
if p.val == root.val or q.val == root.val:
flag=1
#return root
left_subtree = lowestCommonAncestor(root.left, p, q)
right_subtree = lowestCommonAncestor(root.right, p, q)
if left_subtree is None and right_subtree is None:
if flag==0:
return None
else:
return root
if left_subtree is not None and right_subtree is not None:
return root
if left_subtree is None:
if flag==1:
if (right_subtree.value!=p && right_subtree.value!=q) || right_subtree.value==root.value:
return right_subtree
elif right_subtree.value!=root.value:
return root
else:
return right_subtree
else:
if flag==1:
if (left_subtree.value!=p && left_subtree.value!=q) || left_subtree.value==root.value:
return left_subtree
elif left_subtree.value!=root.value:
return root
else:
return left_subtree

The idea is like this: we recursively search p and q in root's left and right subtree. If the result of the left subtree is null, then it means p and q is not in root's left so we could safely conclude that the LCA must reside in root's right subtree. Similar conclusion holds true if the result of right subtree is null. But if neither of them is null, that indicates that p and q take either side of the root. Therefore, root is the LCA.
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if (root == null) {
return root;
}
if (root == p || root == q) {
return root;
}
TreeNode left = lowestCommonAncestor(root.left, p, q);
TreeNode right= lowestCommonAncestor(root.right, p, q);
if (left != null && right != null) {
return root;
} else if (left != null) {
return left;
} else {
return right;
}
}
}

var lowestCommonAncestor = function(root, p, q) {
const lca = (root) => {
// Check if the root is the value, is yes then just return the root
if (!root || root.val === p.val || root.val === q.val){
return root;
}
// Traverse through left and right tree
let L = lca(root.left);
let R = lca(root.right);
// If we have left and right node, which means val1 and val2 are on the either side of root,
// then return root else return L or R
if (L && R)
return root;
return L ? L : R;
}
return lca(root) || -1;
};

Related

Removing a node from binary tree

I'm currently working on leetcode problem 366 where we have to find list of lists that contains values of leaves of each generation. I wanted to achieve this by recursion where if a node does not have left or right child, the value is recorded then the node removed by setting it to None. Here is my code:
def findLeaves(self, root: Optional[TreeNode]) -> List[List[int]]:
leaf_list = []
sub_list = []
def traverse(node):
if node == None:
return
if node.left == None and node.right == None:
sub_list.append(node.val)
node = None
return
traverse(node.left)
traverse(node.right)
return root
while True:
if root == None:
break
sub_list = []
traverse(root)
leaf_list.append(sub_list)
print(leaf_list)
return leaf_list
The problem seems to be that when a certain node is set to None, that change isn't retained. Why is it that I can't set a node to None to remove it?
Thanks
The tree can only be mutated when you assign to one if its node's attributes. An assignment to a variable, only changes what the variable represents. Such assignment never impacts whatever previous value that variable had. Assigning to a variable is like switching from one value to another without affecting any data structure. So you need to adapt your code such that the assignment of None is done to a left or right attribute.
The exception is for the root node itself. When the root is a leaf, then there is no parent to mutate. You will then just discard the tree and switch to an empty one (None).
One way to achieve this, is to use the return value of traverse to update the child-reference (left or right) that the caller of traverse needs to update.
Here is your code with those adaptations:
def findLeaves(root):
sub_list = []
def traverse(node):
if not node:
return
if not node.left and not node.right:
sub_list.append(node.val)
return # By returning None, the parent can remove it
node.left = traverse(node.left) # Assign the returned node reference
node.right = traverse(node.right)
return node # Return the node (parent does not need to remove it)
leaf_list = []
while root:
sub_list = []
root = traverse(root)
leaf_list.append(sub_list)
return leaf_list

How to fix NoneType error in Python Binary Search Tree?

I'm creating a basic binary search tree program where the nodes have to be strings however, I keep getting this error:
'builtins.AttributeError: 'NoneType' object has no attribute 'addNode'
I'm a bit confused because I thought you had to declare the children nodes as None. My code is below (please excuse the messiness and extra print statements):
class BinarySearchTree:
#constructor with insertion value & left/right nodes as None
def __init__(self, data):
self.data = data
self.left = None
self.right = None
#function to insert node
def addNode(root, data):
#when tree doesn't exist
if root == None:
return BinarySearchTree(data)
else:
#when node is already in tree
if root.data == data:
return root
#smaller values go left
elif data < root.data:
root.left.addNode(data)
#bigger values go right
else:
root.right.addNode(data)
return root
#function to find smallest node value (to help with deletion)
def smallestNode(root):
node = root
#loop goes to lowest left leaf
while(node.left is not None):
node = node.left
return node
#function to delete node
def removeNode(root, data):
if root == None:
return root
#when node to be deleted in smaller than root, go left
if data < root.data:
root.left = root.left.removeNode(data)
#when node to be deleted in bigger than root, go right
elif data > root.data:
root.right = root.right.removeNode(data)
##when node to be deleted in the same as root...
else:
#when node has only 1 or 0 children
if root.right == None:
move = root.left
root = None
return move
elif root.left == None:
move = root.right
root = None
return move
#when node has 2 children, copy then delete smallest node
move = root.right.smallestNode()
root.data = move.data
root.right = root.right.removeNode(move.data)
return root
def findNode(root, data):
#if current node is equal to data value then return the root
if root.data == data or root == None:
return root
#if current node is greater than the data value then, search to the left
elif data < root.data:
return root.left.findNode(data)
#if current node is less than the data value then, search to the right
else:
return root.right.findNode(data)
def createBST(keys):
root = BinarySearchTree(keys[0])
for i in range(1,len(keys)):
root.addNode(keys[i])
return root
print('Hi! Welcome to the Binary Search Tree Builder')
print('Here are your options below:')
print('1) Build new tree')
print('2) Add a node')
print('3) Find a node')
print('4) Delete a node')
choice = int(input('What would you like to do?: '))
if choice == 1:
nodes = list(input("Enter the strings you would like to build your tree from (separate by a space): ").split())
print(nodes)
tree = createBST(nodes)
print(tree)
I'm wondering where exactly is this error coming from and how can I fix it? Also, if you see any other problems occuring in my code, please let me know!
You have conflated the notion of "tree node" and "tree". What you have there is a mixture of the two. Remember, the first parameter to ALL member functions should be "self". Replacing "root" by "self" might make your problem more clear.
So, you might create a BinaryTree class, which has a single member called self.root that holds a BinaryTreeNode object, once you have a node. The nodes will hold the left and right values, each of which will either have None or a BinaryTreeNode object. The node class probably doesn't need much code -- just self.left and self.right.
The BinaryTree class will have an addNode member that knows how to traverse the tree to find the right spot, but when you find the spot, you just set self.left = BinaryTreeNode(...). A node does not know about the tree, so a node does not know how to add new nodes. That's a function of the tree itself.
Does that make your path forward more clear?

BST tree search easy leetcode

Given the root node of a binary search tree (BST) and a value. You need to find the node in the BST that the node's value equals the given value. Return the subtree rooted with that node. If such node doesn't exist, you should return NULL.
this is what i get for my code:
class Solution:
def searchBST(self, root: TreeNode, val: int) -> TreeNode:
if root == None:
return None
elif root.val == val:
return root
elif root.val>val:
root = self.searchBST(root.left,val)
else:
root = self.searchBST(root.right,val)
which seems to output None.
but if replace the line
root = self.searchBST(root.left,val)
with
return self.searchBST(root.left,val)
same with root.right
then it works.
I am not too good at recursion but how can we do
return self.searchBST(root.left,val)
doesnt searchBST(..) return a TreeNode so dont we have to put the treenode in the variable root?
No as mentioned in question you need to return the node that matches the val.
In order to do that you have to return the address of the node if you find the value and None if does not.
Inorder to back propagate the value either the root address or Null(in case of not found) so you must return some address at every step.
If you are having problem with recursion go with the iterative traversal.
root iterativeSearch(struct Node* root, int key)
{
// Traverse untill root reaches to dead end
while (root != NULL) {
// pass right subtree as new tree
if (key > root->data)
root = root->right;
// pass left subtree as new tree
else if (key < root->data)
root = root->left;
else
return root; // if the key is found return 1
}
return Null;
}
Go to this for recursion visualisations:https://www.cs.usfca.edu/~galles/visualization/BST.html
You have to explicitly tell Python what you want the function to return. That's what you are doing with the return None and the return root lines.
The the left and right cases, you are only changing the local value of the parameter root, not changing anything outside of the scope of the function.
No explicit return is the same as return None.
Replacing the two root = by return should indeed do the work.
class Solution(object):
def is_leaf(self,root):
return root.left is None and root.right is None
def searchBST(self, root, val):
if root is None:
return root
if self.is_leaf(root):
if root.val == val:
return root
return None
if root.val == val:
return root
elif val < root.val:
return self.searchBST(root.left,val)
else:
return self.searchBST(root.right,val)

Inorder successor in a binary search tree

This is a common algorithm question. I'm trying to find the inorder successor in a binary search tree. Here's my code
def inorderSuccessor(self, root, p):
"""
:type root: TreeNode
:type p: TreeNode
:rtype: TreeNode
"""
# if Node has a right child, go all the way down
if p.right:
curr = p
while curr.left:
curr = curr.left
return curr
# first ancestor whose left child the node is
ans = None
curr = root
while curr is not p:
if curr.val < p.val:
curr = curr.right
else:
ans = curr
curr = curr.left
return ans
The problem is that this doesn't work when p is the highest node in the tree. I've been scratching my head over how to get this edge case going.
You can implement a method within your BST Class as below
def InOrderSucc(self,childNode):
if(self.search(childNode)):
if not (self.data == childNode):
return(self.right.InOrderSucc(childNode))
else:
if(self.right):
return(self.right.data)
else:
return None
else:
return False
where childNode is the Node you are requesting to find its InOrder Successor, Noting that the InOrder Successor will always be the right Child.

Help me understand Inorder Traversal without using recursion

I am able to understand preorder traversal without using recursion, but I'm having a hard time with inorder traversal. I just don't seem to get it, perhaps, because I haven't understood the inner working of recursion.
This is what I've tried so far:
def traverseInorder(node):
lifo = Lifo()
lifo.push(node)
while True:
if node is None:
break
if node.left is not None:
lifo.push(node.left)
node = node.left
continue
prev = node
while True:
if node is None:
break
print node.value
prev = node
node = lifo.pop()
node = prev
if node.right is not None:
lifo.push(node.right)
node = node.right
else:
break
The inner while-loop just doesn't feel right. Also, some of the elements are getting printed twice; may be I can solve this by checking if that node has been printed before, but that requires another variable, which, again, doesn't feel right. Where am I going wrong?
I haven't tried postorder traversal, but I guess it's similar and I will face the same conceptual blockage there, too.
Thanks for your time!
P.S.: Definitions of Lifo and Node:
class Node:
def __init__(self, value, left=None, right=None):
self.value = value
self.left = left
self.right = right
class Lifo:
def __init__(self):
self.lifo = ()
def push(self, data):
self.lifo = (data, self.lifo)
def pop(self):
if len(self.lifo) == 0:
return None
ret, self.lifo = self.lifo
return ret
Start with the recursive algorithm (pseudocode) :
traverse(node):
if node != None do:
traverse(node.left)
print node.value
traverse(node.right)
endif
This is a clear case of tail recursion, so you can easily turn it into a while-loop.
traverse(node):
while node != None do:
traverse(node.left)
print node.value
node = node.right
endwhile
You're left with a recursive call. What the recursive call does is push a new context on the stack, run the code from the beginning, then retrieve the context and keep doing what it was doing. So, you create a stack for storage, and a loop that determines, on every iteration, whether we're in a "first run" situation (non-null node) or a "returning" situation (null node, non-empty stack) and runs the appropriate code:
traverse(node):
stack = []
while !empty(stack) || node != None do:
if node != None do: // this is a normal call, recurse
push(stack,node)
node = node.left
else // we are now returning: pop and print the current node
node = pop(stack)
print node.value
node = node.right
endif
endwhile
The hard thing to grasp is the "return" part: you have to determine, in your loop, whether the code you're running is in the "entering the function" situation or in the "returning from a call" situation, and you will have an if/else chain with as many cases as you have non-terminal recursions in your code.
In this specific situation, we're using the node to keep information about the situation. Another way would be to store that in the stack itself (just like a computer does for recursion). With that technique, the code is less optimal, but easier to follow
traverse(node):
// entry:
if node == NULL do return
traverse(node.left)
// after-left-traversal:
print node.value
traverse(node.right)
traverse(node):
stack = [node,'entry']
while !empty(stack) do:
[node,state] = pop(stack)
switch state:
case 'entry':
if node == None do: break; // return
push(stack,[node,'after-left-traversal']) // store return address
push(stack,[node.left,'entry']) // recursive call
break;
case 'after-left-traversal':
print node.value;
// tail call : no return address
push(stack,[node.right,'entry']) // recursive call
end
endwhile
Here is a simple in-order non-recursive c++ code ..
void inorder (node *n)
{
stack s;
while(n){
s.push(n);
n=n->left;
}
while(!s.empty()){
node *t=s.pop();
cout<<t->data;
t=t->right;
while(t){
s.push(t);
t = t->left;
}
}
}
def print_tree_in(root):
stack = []
current = root
while True:
while current is not None:
stack.append(current)
current = current.getLeft();
if not stack:
return
current = stack.pop()
print current.getValue()
while current.getRight is None and stack:
current = stack.pop()
print current.getValue()
current = current.getRight();
def traverseInorder(node):
lifo = Lifo()
while node is not None:
if node.left is not None:
lifo.push(node)
node = node.left
continue
print node.value
if node.right is not None:
node = node.right
continue
node = lifo.Pop()
if node is not None :
print node.value
node = node.right
PS: I don't know Python so there may be a few syntax issues.
Here is a sample of in order traversal using stack in c# (.net):
(for post order iterative you may refer to: Post order traversal of binary tree without recursion)
public string InOrderIterative()
{
List<int> nodes = new List<int>();
if (null != this._root)
{
Stack<BinaryTreeNode> stack = new Stack<BinaryTreeNode>();
var iterativeNode = this._root;
while(iterativeNode != null)
{
stack.Push(iterativeNode);
iterativeNode = iterativeNode.Left;
}
while(stack.Count > 0)
{
iterativeNode = stack.Pop();
nodes.Add(iterativeNode.Element);
if(iterativeNode.Right != null)
{
stack.Push(iterativeNode.Right);
iterativeNode = iterativeNode.Right.Left;
while(iterativeNode != null)
{
stack.Push(iterativeNode);
iterativeNode = iterativeNode.Left;
}
}
}
}
return this.ListToString(nodes);
}
Here is a sample with visited flag:
public string InorderIterative_VisitedFlag()
{
List<int> nodes = new List<int>();
if (null != this._root)
{
Stack<BinaryTreeNode> stack = new Stack<BinaryTreeNode>();
BinaryTreeNode iterativeNode = null;
stack.Push(this._root);
while(stack.Count > 0)
{
iterativeNode = stack.Pop();
if(iterativeNode.visted)
{
iterativeNode.visted = false;
nodes.Add(iterativeNode.Element);
}
else
{
iterativeNode.visted = true;
if(iterativeNode.Right != null)
{
stack.Push(iterativeNode.Right);
}
stack.Push(iterativeNode);
if (iterativeNode.Left != null)
{
stack.Push(iterativeNode.Left);
}
}
}
}
return this.ListToString(nodes);
}
the definitions of the binarytreenode, listtostring utility:
string ListToString(List<int> list)
{
string s = string.Join(", ", list);
return s;
}
class BinaryTreeNode
{
public int Element;
public BinaryTreeNode Left;
public BinaryTreeNode Right;
}
Simple iterative inorder traversal without recursion
'''iterative inorder traversal, O(n) time & O(n) space '''
class Node:
def __init__(self, value, left = None, right = None):
self.value = value
self.left = left
self.right = right
def inorder_iter(root):
stack = [root]
current = root
while len(stack) > 0:
if current:
while current.left:
stack.append(current.left)
current = current.left
popped_node = stack.pop()
current = None
if popped_node:
print popped_node.value
current = popped_node.right
stack.append(current)
a = Node('a')
b = Node('b')
c = Node('c')
d = Node('d')
b.right = d
a.left = b
a.right = c
inorder_iter(a)
State can be remembered implicitly,
traverse(node) {
if(!node) return;
push(stack, node);
while (!empty(stack)) {
/*Remember the left nodes in stack*/
while (node->left) {
push(stack, node->left);
node = node->left;
}
/*Process the node*/
printf("%d", node->data);
/*Do the tail recursion*/
if(node->right) {
node = node->right
} else {
node = pop(stack); /*New Node will be from previous*/
}
}
}
#Victor, I have some suggestion on your implementation trying to push the state into the stack. I don't see it is necessary. Because every element you take from the stack is already left traversed. so instead of store the information into the stack, all we need is a flag to indicate if the next node to be processed is from that stack or not. Following is my implementation which works fine:
def intraverse(node):
stack = []
leftChecked = False
while node != None:
if not leftChecked and node.left != None:
stack.append(node)
node = node.left
else:
print node.data
if node.right != None:
node = node.right
leftChecked = False
elif len(stack)>0:
node = stack.pop()
leftChecked = True
else:
node = None
Little Optimization of answer by #Emadpres
def in_order_search(node):
stack = Stack()
current = node
while True:
while current is not None:
stack.push(current)
current = current.l_child
if stack.size() == 0:
break
current = stack.pop()
print(current.data)
current = current.r_child
This may be helpful (Java implementation)
public void inorderDisplay(Node root) {
Node current = root;
LinkedList<Node> stack = new LinkedList<>();
while (true) {
if (current != null) {
stack.push(current);
current = current.left;
} else if (!stack.isEmpty()) {
current = stack.poll();
System.out.print(current.data + " ");
current = current.right;
} else {
break;
}
}
}
class Tree:
def __init__(self, value):
self.left = None
self.right = None
self.value = value
def insert(self,root,node):
if root is None:
root = node
else:
if root.value < node.value:
if root.right is None:
root.right = node
else:
self.insert(root.right, node)
else:
if root.left is None:
root.left = node
else:
self.insert(root.left, node)
def inorder(self,tree):
if tree.left != None:
self.inorder(tree.left)
print "value:",tree.value
if tree.right !=None:
self.inorder(tree.right)
def inorderwithoutRecursion(self,tree):
holdRoot=tree
temp=holdRoot
stack=[]
while temp!=None:
if temp.left!=None:
stack.append(temp)
temp=temp.left
print "node:left",temp.value
else:
if len(stack)>0:
temp=stack.pop();
temp=temp.right
print "node:right",temp.value
Here's an iterative C++ solution as an alternative to what #Emadpres posted:
void inOrderTraversal(Node *n)
{
stack<Node *> s;
s.push(n);
while (!s.empty()) {
if (n) {
n = n->left;
} else {
n = s.top(); s.pop();
cout << n->data << " ";
n = n->right;
}
if (n) s.push(n);
}
}
Here is an iterative Python Code for Inorder Traversal ::
class Node:
def __init__(self, data):
self.data = data
self.left = None
self.right = None
def inOrder(root):
current = root
s = []
done = 0
while(not done):
if current is not None :
s.append(current)
current = current.left
else :
if (len(s)>0):
current = s.pop()
print current.data
current = current.right
else :
done =1
root = Node(1)
root.left = Node(2)
root.right = Node(3)
root.left.left = Node(4)
root.left.right = Node(5)
inOrder(root)
For writing iterative equivalents of these recursive methods, we can first understand how the recursive methods themselves execute over the program's stack. Assuming that the nodes do not have their parent pointer, we need to manage our own "stack" for the iterative variants.
One way to start is to see the recursive method and mark the locations where a call would "resume" (fresh initial call, or after a recursive call returns). Below these are marked as "RP 0", "RP 1" etc ("Resume Point"). Take example of inorder traversal. (I will present in C language, but same methodology applies to any general language):
void in(node *x)
{
/* RP 0 */
if(x->lc) in(x->lc);
/* RP 1 */
process(x);
if(x->rc) in(x->rc);
/* RP 2 */
}
Its iterative variant:
void in_i(node *root)
{
node *stack[1000];
int top;
char pushed;
stack[0] = root;
top = 0;
pushed = 1;
while(top >= 0)
{
node *curr = stack[top];
if(pushed)
{
/* type (x: 0) */
if(curr->lc)
{
stack[++top] = curr->lc;
continue;
}
}
/* type (x: 1) */
pushed = 0;
process(curr);
top--;
if(curr->rc)
{
stack[++top] = curr->rc;
pushed = 1;
}
}
}
The code comments with (x: 0) and (x: 1) correspond to the "RP 0" and "RP 1" resume points in the recursive method. The pushed flag helps us deduce one of these two resume-points. We do not need to handle a node at its "RP 2" stage, so we do not keep such node on stack.
I think part of the problem is the use of the "prev" variable. You shouldn't have to store the previous node you should be able to maintain the state on the stack (Lifo) itself.
From Wikipedia, the algorithm you are aiming for is:
Visit the root.
Traverse the left subtree
Traverse the right subtree
In pseudo code (disclaimer, I don't know Python so apologies for the Python/C++ style code below!) your algorithm would be something like:
lifo = Lifo();
lifo.push(rootNode);
while(!lifo.empty())
{
node = lifo.pop();
if(node is not None)
{
print node.value;
if(node.right is not None)
{
lifo.push(node.right);
}
if(node.left is not None)
{
lifo.push(node.left);
}
}
}
For postorder traversal you simply swap the order you push the left and right subtrees onto the stack.

Categories

Resources