Iterative postorder traversal

Iterative postorder traversal

In last two posts, iterative inorder and iterative preorder traversal, we learned how stack can be used to replace recursion and why recursive implementation can be dangerous in production environment. In this post, let’s discuss iterative postorder traversal of binary tree which is most complex of all traversals. What is post order traversal ? A traversal where  left and right subtrees are visited before root is processed. For example, post order traversal of below tree would be : [1,6,5,12,16,14,10]

iterative postorder traversal

Iterative postorder traversal  : Thoughts

Let’s look at the recursive implementation of postorder.

    private void postOrder(Node root){
        if(root == null) return;

        postOrder(root.left);
        postOrder(root.right);
        System.out.println(root.value);

    }

As we are going into left subtree and then directly to right subtree, without visiting root node. Can you find the similarity of structure between preorder and postorder implementation?  Can we reverse the entire preorder traversal to get post order traversal? Reverse preorder will give us right child, left child and then root node, however order expected is left child, right child and root child.
Do you remember we pushed left and right node onto stack in order where right child went before left. How about reversing that?

There is one more problem with just reversing the preorder. In preorder, a node was processed as soon as popped from stack, like root node will  be the first node to be processed. However, in postorder, root node is processed last. So, we actually need the order of processing too be reversed. What better than using a stack to store the reverse order of root nodes to processed.
All in all, we will be using two stacks, one to store left and right child, second to store processing order of nodes.

  1. Create two stacks s an out and push root node onto s
  2. While stack s is not empty
    1. op from stack s, current = s.pop
    2. Put current onto stack out.
    3. Put left and right child of current on to stack s
  3. Pop everything from out stack and process it.

Postorder traversal with two stacks : Implementation

package com.company.BST;

import java.util.Stack;

/**
 * Created by sangar on 22.5.18.
 */
public class BinarySearchTreeTraversal {

    private Node root;

    public void BinarySearchTree(){
        root = null;
    }

    public class Node {
        private int value;
        private Node left;
        private Node right;

        public Node(int value) {
            this.value = value;
            this.left = null;
            this.right = null;
        }
    }

    public void insert(int value){
        this.root =  insertNode(this.root, value);
    }

    private Node insertNode(Node root, int value){
        if(root == null){
            //if this node is root of tree
            root = new Node(value);
        }
        else{
            if(root.value > value){
                //If root is greater than value, node should be added to left subtree
                root.left = insertNode(root.left, value);
            }
            else{
                //If root is less than value, node should be added to right subtree
                root.right = insertNode(root.right, value);
            }
        }
        return root;
    }
    private void postOrder(Node root){
       if(root == null) return;

       postOrder(root.left);
       postOrder(root.right);
       System.out.println(root.value);
    }

    public void postOrderTraversal(){
        postOrderIterative(root);
    }

    private void postOrderIterative(Node root){
        Stack<Node> out = new Stack<>();
        Stack<Node> s = new Stack<>();

        s.push(root);

        while(!s.empty()){
            Node current = s.pop();

            out.push(current);
            if(current.left != null) s.push(current.left);
            if(current.right != null) s.push(current.right);
        }

        while(!out.empty()){
            System.out.println(out.pop().value);
        }
    }
}

Complexity of iterative implementation is O(n) with additional space complexity of O(n).

Can we avoid using two stack, and do it with one stack? Problem with root in postorder traversal is that it is visited three times, moving down from parent, coming up from left child and coming up from right child. When should be the node processed? Well, when we are coming up from right child.

How can we keep track of how the current node was reached? If we keep previous pointer, there are three cases:

  1. Previous node is parent of current node, we reached node from parent node, nothing is done.
  2. Previous node is left child of current node, it means we have visited left child, but still not visited right child, move to right child of current node.
  3. Previous node is right child of current node, it means  we have visited left and right child of current node,  process the current node.

Let’s formulate  postorder traversal algorithm then.

  1. Push root node onto stack s, set prev = null.
  2. Repeat below steps till stack is not empty (!s.empty())
  3. current = s.pop(), pop from the stack.
  4. If (prev == null || prev.left == current || prev.right == current) then
    1. If current.left != null, push current.left onto stack.
    2. If current.right != null, push current.right onto stack.
    3. If current.left == current.right == null, process current.
  5. If current.left == prev, i.e. moving up left child then
    1. If current.right == null, process current.
    2. If current.right != null, push it to stack.
  6. If current.right == prev i.e moving up from right child
    1. process current.
    2. prev = current, current = s.pop.

Iterative Postorder traversal : Implementation

package com.company.BST;

import java.util.Stack;

/**
 * Created by sangar on 22.5.18.
 */
public class BinarySearchTreeTraversal {

    private Node root;

    public void BinarySearchTree(){
        root = null;
    }

    public class Node {
        private int value;
        private Node left;
        private Node right;

        public Node(int value) {
            this.value = value;
            this.left = null;
            this.right = null;
        }
    }

    public void insert(int value){
        this.root =  insertNode(this.root, value);
    }
  
    private Node insertNode(Node root, int value){
        if(root == null){
            //if this node is root of tree
            root = new Node(value);
        }
        else{
            if(root.value > value){
                //If root is greater than value, node should be added to left subtree
                root.left = insertNode(root.left, value);
            }
            else{
                //If root is less than value, node should be added to right subtree
                root.right = insertNode(root.right, value);
            }
        }
        return root;
    }


    private void inorder(Node root){
            if(root == null) return;

            if(root.left != null) inorder(root.left);
            System.out.println(root.value);
            if(root.right != null) inorder(root.right);
        }

        private void preOrder(Node root){
            if(root == null) return;

            System.out.println(root.value);
            preOrder(root.left);
            preOrder(root.right);
        }

        private void postOrder(Node root){
            if(root == null) return;

            postOrder(root.left);
            postOrder(root.right);
            System.out.println(root.value);

        }
        public void postOrderTraversal(){
          //  postOrder(root);
            postOrderIterative2(root);
            //postOrderIterative(root);
        }

        private void postOrderIterative2(Node root){
            Node prev = null;
            Stack<Node> s = new Stack<>();

            s.push(root);

            while(!s.empty()){
                Node current  = s.peek();
                if(prev == null || ( prev.left == current || prev.right == current )){
                    if(current.left != null) s.push(current.left);
                    else if(current.right != null) s.push(current.right);
                }
                else if(prev == current.left){
                    if(current.right != null) s.push(current.right);
                }else{
                    System.out.println(current.value);
                    s.pop();
                }

                prev = current;
            }
    }

}

Complexity of code is O(n) again, with additional space complexity of O(n).

Please share if there is something wrong or missing. If you want to contribute and share your learning with thousands of learners across the world, please reach out to us at communications@algorithmsandme.com

Height of binary tree

Height of binary tree

One of the most basic problems on binary search tree is to find height of binary search tree or binary tree. First of all, what do we mean by height of binary search tree or height of binary tree? Height of tree is the maximum distance between the root node and any leaf node of the tree. For example, height of tree given below is 5, distance between node(10) and node(8). Note that we have multiple lea nodes, however we chose the node which s farthest from the root node.

height of binary tree

Height of binary tree : Thoughts

Brute force method to find height will be to calculate distance of each node from the root and take the maximum of it. As we will traversing each node of tree complexity will be O(n) and we need O(2logn) space to store distance for each leaf node.

What if we go bottom up instead of measuring distance of leaf nodes from root? What will be height of leaf node? At leaf node, there is no tree below it, hence height should be 1, which is node itself. What will be height of empty tree where root itself is null? It will be zero.
What if a node has a left subtree? Then height of subtree at that node will be height of left subtree + 1 (for the node itself). Same is true if node has only right subtree.

Interesting case is when node has both left and right subtree. Which height we should take to get height of subtree at node? As we are looking for maximum distance, we should take maximum of both subtrees and add 1 to get height at that node.

As we are going bottom up and building the height up from leaf to node, it is necessary to pass on height of left subtree and right subtree to root node. It means we have to process subtrees before root node. What kind of traversal is it? As in Delete binary search tree and Mirror binary search tree this problem is also postorder traversal of binary tree with specific processing at root node.

Let’s take and example and see how this method works? Given below binary tree,find height of it.

height of binary tree

We have to start from bottom and for that follow the path till node is current node is null. At root node(10), is it node null? No, then move down the left subtree.

Is node(5) null? Nope, again move down to left subtree.

At node(4), it is not null, hence we move down to left subtree. But as left child of node(4) is null, it we will return 0 as height of an empty binary tree should be 0. Again, node(4) does not even have right child, so from right side too it gets a zero. What will be height of node(40) then? Max(0,0 ) + 1 = 1, which it returns back to parent node(5).

Back at node(5), we go the height of left subtree, there is right subtree too, so we will find height of it, before judging the height of subtree at node(5). So move down the right side of node(5).

Node(7) is not null, so move down the left subtree of it, which is node(6).

Node(6) is also not null, hence we move down the left subtree which is null. Null subtree returns 0. It is same for right subtree of node(6). So, node(6) return max(0,0) + 1 = 1 to parent node.

Back at node(7), there is right subtree too, so move down it to node(9).

As node(9) is not null, move down the left child which is node(8).

We move left of node(8) which is null and even right subtree is null, as all leaf node, it also return 1 to parent node.

 

At node(9), right child is null which return 0. So what should be height of node(9)? It will be max(1,0) + 1 = 2. 1 is height of left subtree and 0 is height of right subtree.
In the same vein, node(7) will return 3 to node(5).

At node(5), return max(1,3) +1 = 4.

 

Now, at node(10), we have height of left subtree let’s calculate height of right subtree. Move down to node(14).

 

Node(14) not null, move to left subtree to node(12).

 

As node(12) is not null, move to left side, which being null, return 0. Similarly for right child, it also returns 0. So, node(12) return max(0,0) +1 to parent node.

Move down to right subtree of node(14) to node(15).

As explained other cases, node(15) too will return 1.

At this point, we have height of left subtree and right subtree of node(14), hence return height  = max(1,1) + 1 = 2 to parent node.

Here, at node(10), we have height of left and right subtrees. What will be height of the binary tree then? it will be max(4,2) + 1 = 5.

Hope this example clarifies how recursive bottom up approach works to find height of binary tree.

Height of binary tree : Implementation

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
 
struct node{
    int value;
    struct node *left;
    struct node *right;
};
typedef struct node Node;

#define MAX(a,b)  (a < b ? b : a)

Node *createNode(int value){
    Node * newNode =  (Node *)malloc(sizeof(Node));
	
    newNode->value = value;
    newNode->right= NULL;
    newNode->left = NULL;
	
    return newNode;
}

Node *addNode(Node *node, int value){
    if(!node) return createNode(value);
        
    if (node->value > value)
        node->left = addNode(node->left, value);
    else
        node->right = addNode(node->right, value);
		
    return node;
}

int height( Node *root){
    if( !root ) return 0;
    
    int lheight = height( root->left);
    int rheight = height( root->right);
	
    return 1 + MAX (lheight, rheight );
}

/* Driver program for the function written above */
int main(){
    Node *root = NULL;
	
    //Creating a binary tree
    root = addNode(root, 30);
    root = addNode(root, 20);
    root = addNode(root, 15);
    root = addNode(root, 25);
    root = addNode(root, 40);
    root = addNode(root, 38);
    root = addNode(root, 39);
    root = addNode(root, 45);
    
    printf( "Height of tree is : %d", height( root));
    
    return 0;
}

Complexity of recursive method is O(n) as we will b scanning all nodes at least once. Be aware of drawback of recursive nature of this implementation as it may lead of stack overflow in production environments.

Two important things we learn from this problem : First how to traverse a tree which is part of solution to many of binary tree problems. Second, how to return values for subtrees to root and process those values at root node. We saw same thing happening in Replace node with sum of children in BST.

Please share if there is something wrong or missing. If you want to contribute and share your knowledge with thousands of learners across world, please reach out to us at communications@algorithmsandme.com

Delete binary search tree

Delete binary search tree

In last post Binary search tree traversals we discussed various kind of traversals of tree like inorder, preorder and post order traversals. One of the many problems which can be solved using these traversals is to delete binary search tree. Problem is : given a binary search tree, delete all nodes of it.

Delete binary tree : Thoughts

As always, we would start from the root of the binary tree. What choice do we have here? We can delete the root node immediately. We can delete left subtree first and then delete root node. Or we can delete left subtree, right subtree and then delete the node.
If we delete root node immediately, we lose access to left and right subtree as root node contains references to these. Deletion of root upfront would have been preorder traversal.

If we delete root node after deleting left subtree, we lose reference to right subtree. So, we can not delete root node before deleting both left and right subtree. That means we will be processing root node last. What kind of traversal is that? Of course postorder traversal, instead of print node, delete node.

Recursive nature of problem is evident that to delete a tree, we have to first delete the subtree and then it’s subtree and so on.

Delete binary search tree : Implementation

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
 
struct node{
	int value;
	struct node *left;
	struct node *right;
};
typedef struct node Node;

void deleteBST(Node *root){
	if(!root)
		return ;
	
	//Process left subtree
	deleteBST(root->left);
	//Process right subtree
	deleteBST(root->right);
	//Free the root node
        root->left = NULL;
        root->right = NULL;
	free(root);
}

Node * createNode(int value){
	Node * newNode =  (Node *)malloc(sizeof(Node));
	newNode->value = value;
	newNode->right= NULL;
	newNode->left = NULL;
	
	return newNode;
}
Node *addNode(Node *node, int value){
	if(node == NULL){
		return createNode(value);
	}
	else{
		if (node->value > value){
			node->left = addNode(node->left, value);
		}
		else{
			node->right = addNode(node->right, value);
		}
	}
	return node;
}

/* Driver program for the function written above */
int main(){
	Node *root = NULL;
	//Creating a binary tree
	root = addNode(root,30);
	root = addNode(root,20);
	root = addNode(root,15);
	root = addNode(root,25);
	root = addNode(root,40);
	root = addNode(root,37);
	root = addNode(root,45);
	
	deleteBST(root);
	
	return 0;
}

Java implementation

package com.company.BST;

import java.util.ArrayList;

/**
 * Created by sangar on 10.5.18.
 */
public class BinarySearchTree {

    private Node root;

    public void BinarySearchTree(){
        root = null;
    }

    public class Node {
        private int value;
        private  Node left;
        private Node right;

        public Node(int value) {
            this.value = value;
            this.left = null;
            this.right = null;
        }
    }

    public void insert(int value){
        this.root =  insertNode(this.root, value);
    }

    private Node insertNode(Node root, int value){
        if(root == null){
            //if this node is root of tree
            root = new Node(value);
        }
        else{
            if(root.value > value){
                /*If root is greater than value, node 
                  should be added to left subtree */
                root.left = insertNode(root.left, value);
            }
            else{
                /* If root is less than value, node 
                should be added to right subtree */
                root.right = insertNode(root.right, value);
            }
        }
        return root;
    }

    public void delete(){
        deleteRecusrive(this.root);
        this.root = null;
    }
    private void deleteRecusrive(Node root){
        if(root == null) return;

        //delete left subtree
        deleteRecusrive(root.left);
        //delete right subtree
        deleteRecusrive(root.right);

        //delete the root, which will be collected by GC
        root.left = null;
        root.right = null;
    }
}

Test class

package com.company.BST;

/**
 * Created by sangar on 10.5.18.
 */
public class BinarySearchTreeTests {
    public static void main (String[] args){
        BinarySearchTree binarySearchTree = new BinarySearchTree();

        binarySearchTree.insert(7);
        binarySearchTree.insert(8);
        binarySearchTree.insert(6);
        binarySearchTree.insert(9);
        binarySearchTree.insert(3);
        binarySearchTree.insert(4);

        binarySearchTree.delete();
        binarySearchTree.inorderTraversal();
    }
}

Delete binary search tree : Example

Let’s see how it works. Given below binary search tree, we have to delete it.

We start with node(10), can we delete it? No we cannot because there is left subtree and right subtree attached to it.


Move down the node(5), and check if it can be deleted. No as  it has left and right child.

delete binary search tree

Again, we move down to left subtree, and new candidate for deletion is node(1). Can we delete it? Yes as it is leaf node with no left or right child.

delete binary tree

After deleting node(1), we move back to it’s parent node(5), we cannot still delete node(5) as there is right subtree to it.

delete a bst

We move down the right subtree, which is node(6). Can we delete it? Yes we can as it’s a leaf node.

delete a binary search tree

Once, we delete node(6), new candidate for deletion is again node(5).  Can we delete node(5) now? Yes as we already deleted left and right subtree of the node, we can safely delete it.

delete binary search tree

After deleting node(5), we move up to it’s parent which is node(10). Can we delete it? No as there is right subtree to it.

Our new candidate for deletion is node(19), can we delete it? Nope, as it has left and right subtree to it.

Move down the left subtree and candidate is node(17).

Delete node(17) and move up to the parent node(19), however, do not delete node(19) still as there is right child of it.

Now, move down to node(21).

Delete node(21) as it is leaf node. After deleting node(21), we move up to parent which is node(19).

Can node(19) be delete now? Yes as left and right subtree have been deleted, parent node can be deleted safely.

Same as other nodes, delete node(10) too.

Complexity of algorithm to delete binary search tree is O(n) as we scan all the nodes of tree at least once.

Please share if there is something wrong or missing. If you want to contribute and share your knowledge with thousands of learners across world, please reach out to us on communications@algorithmsandme.com

Binary search tree traversals

Binary search tree traversals

Most of the problems on binary search tree can be solved using one or other traversal of tree. There are three types of binary search tree traversals : Preorder traversal, Inorder traversal and Postorder traversal. Let’s discuss each one in detail.

Preorder traversal of BST

Preorder traversal means traverse the root node first, then left subtree and at last traverse right subtree. For example, given below tree, preorder traversal will be 10,5,1,,6,19,17,21.

binary search tree traversals

As we already know that binary search tree is recursive data structure, any traversal can be solved recursively. Start with the root, then do a preorder traversal of left subtree and then at last do the preorder traversal of right subtree.

In above example,  after traversing root node(10), left subtree is traversed in preorder [5,1,6]. Same is true after traversing node(5).

Preorder traversal implementation

package com.company.BST;

import java.util.ArrayList;

/**
 * Created by sangar on 10.5.18.
 */
public class BinarySearchTree {

    private Node root;

    public void BinarySearchTree(){
        root = null;
    }

    public class Node {
        private int value;
        private  Node left;
        private Node right;

        public Node(int value) {
            this.value = value;
            this.left = null;
            this.right = null;
        }
    }

    public void insert(int value){
        this.root =  insertNode(this.root, value);
    }

    private Node insertNode(Node root, int value){
        if(root == null){
            //if this node is root of tree
            root = new Node(value);
        }
        else{
            if(root.value > value){
                //If root is greater than value, node should be added to left subtree
                root.left = insertNode(root.left, value);
            }
            else{
                //If root is less than value, node should be added to right subtree
                root.right = insertNode(root.right, value);
            }
        }
        return root;
    }

    private void inorder(Node root){
        if(root == null) return;

        if(root.left != null) inorder(root.left);
        System.out.println(root.value);
        if(root.right != null) inorder(root.right);
    }
}

Inorder traversal of BST

Inorder traversal means traverse left subtree first, then root node and at last traverse right subtree. For example, given below tree, inorder traversal will be 1,5,6,10,17,19,21.

preorder travesal binary search tree

Again following the recursive strategy, if node has left child, do inorder traversal on left subtree, once inorder traversal of left subtree is done, visit root node and then again do inorder traversal of right subtree.

In above example,  before traversing root node(10), left subtree is traversed in inorder [1,5,6]. Same is true before traversing node(5).

Inorder traversal implementation

package com.company.BST;

import java.util.ArrayList;

/**
 * Created by sangar on 10.5.18.
 */
public class BinarySearchTree {

    private Node root;

    public void BinarySearchTree(){
        root = null;
    }

    public class Node {
        private int value;
        private  Node left;
        private Node right;

        public Node(int value) {
            this.value = value;
            this.left = null;
            this.right = null;
        }
    }

    public void insert(int value){
        this.root =  insertNode(this.root, value);
    }

    private Node insertNode(Node root, int value){
        if(root == null){
            //if this node is root of tree
            root = new Node(value);
        }
        else{
            if(root.value > value){
                //If root is greater than value, node should be added to left subtree
                root.left = insertNode(root.left, value);
            }
            else{
                //If root is less than value, node should be added to right subtree
                root.right = insertNode(root.right, value);
            }
        }
        return root;
    }

    private void inorder(Node root){
        if(root == null) return;

        if(root.left != null) inorder(root.left);
        System.out.println(root.value);
        if(root.right != null) inorder(root.right);
    }
}

Postorder traversal of BST

Postorder traversal means traverse left subtree first, then right subtree and at last visit root node. For example, given below tree, postorder traversal will be 1,6,5,17,21,19,10.

postorder traversal of binary search tree

Again following the recursive strategy, if node has left child, do postorder traversal on left subtree, then do postorder traversal of right subtree and finally visit root node.

In above example,  before traversing root node(10), left subtree is traversed in postorder [1,6,5] and then right subtree is traversed in postorder [17,21,19] and then finally node(10).

Postorder traversal implementation

package com.company.BST;

import java.util.ArrayList;

/**
 * Created by sangar on 10.5.18.
 */
public class BinarySearchTree {

    private Node root;

    public void BinarySearchTree(){
        root = null;
    }

    public class Node {
        private int value;
        private  Node left;
        private Node right;

        public Node(int value) {
            this.value = value;
            this.left = null;
            this.right = null;
        }
    }

    public void insert(int value){
        this.root =  insertNode(this.root, value);
    }

    private Node insertNode(Node root, int value){
        if(root == null){
            //if this node is root of tree
            root = new Node(value);
        }
        else{
            if(root.value > value){
                //If root is greater than value, node should be added to left subtree
                root.left = insertNode(root.left, value);
            }
            else{
                //If root is less than value, node should be added to right subtree
                root.right = insertNode(root.right, value);
            }
        }
        return root;
    }

    private void preOrder(Node root){
        if(root == null) return;

        System.out.println(root.value);
        preOrder(root.left);
        preOrder(root.right);
    }
}

In next few posts, we will discuss problems which can be solved using these traversals.

Please share if there is something wrong or missing. If you want to contribute and share your knowledge with thousands of learners across the world, please reach out to us at communications@algorithmsandme.com