GfG QA is closing soon... Please refer PRACTICE or GfG now on wards !!

Implement an iterator over a binary search tree (BST)

‚ÄčImplement an iterator over a binary search tree (BST). Your iterator will be initialized with the root node of a BST.

The first call to next() will return the smallest number in BST. Calling next() again will return the next smallest number in the BST, and so on.

 

Note: next() and hasNext() should run in average O(1) time and uses O(h) memory, whereh is the height of the tree.
Try to optimize the additional space complexity apart from the amortized time complexity.

asked Oct 11, 2015 by Swanky
edited Oct 11, 2015 by Swanky

3 Answers

Approach 1 : Do an inorder traversal of the tree and store the entries in an array with the current pointer set to the start of the array. hasNext checks if the pointer is less than the size of the array. next() would return the element at the current position incrementing the position by 1.
However, this has an additional space complexity of O(N) where N = number of nodes in the tree.

Approach 2 : Lets look at the version of this problem when the trees have a back pointer. We can solve the problem without using additional space. When you are on node N and are asked for next element, you obviously won’t go to the left subtree as all the elements there are smaller than N. We would go to the smallest number in the right subtree if the right subtree is not null. If the right subtree is null, that means that we need to move up, and keep moving up till we are coming from the right subtree.
Now we don’t have the back pointer in this case. So, we need something to keep track of the path from root to the current node, so we can move to the parent when needed. Do note that storing the path from root to the current node only requires memory equivalent to the length of the path which is the depth of the tree. Also, we can track the path using stack.

// Author :: Gaurav Ahirwar
#include<bits/stdc++.h>
using namespace std;

struct node 
{	
    int data;
    struct node* left, *right;
};
typedef struct node* Node;
typedef struct node node;

Node newNode(int data) {
	
    Node temp = (Node)malloc(sizeof(struct node));
    temp->data  = data;
    temp->left  = temp->right = NULL;
    return(temp);
}

class BSTIterator {
    public:
        stack<node *> myStack;

        BSTIterator(node *root) {
            pushAll(root);
        }

        // return whether we have a next smallest number 
        bool hasNext() {
            return !myStack.empty();
        }

        // return the next smallest number
        int next() {
            node *tmpNode = myStack.top();
            myStack.pop();
            pushAll(tmpNode->right);
            return tmpNode->data;
        }

    private:
        void pushAll(node *root) {
            while (root != NULL) {
                myStack.push(root);
                root = root->left;
            }
        }
};

int main() {
  	
	// Let us construct the BST shown in the above figure
    Node root  		  = newNode(4);
    root->left        = newNode(2);
    root->right       = newNode(6);
    root->left->left  = newNode(1);
    root->left->right = newNode(3);
    root->right->left  = newNode(5);
    root->right->right = newNode(7);
 	/* Constructed binary tree is 
            4
          /   \
        2      6
      /  \	  /	\
    1     3  5  7
  
  */
  
  BSTIterator it(root);
  while (it.hasNext()) cout << it.next() << " ";
  
  
  return 0;
}
answered Oct 11, 2015 by Mr.Lazy

In case of left skew tree, h = n, so space required is O(n) in worst case where n is number of nodes in tree. correct me if I am wrong.

class Node{
	int n;
	Node(int n)
	{
		this.n = n;
	}
	public String toString(){
		return ""+n;
	}
}
public class Tree implements Iterable<Tree>{
	Node root;
	Tree left;
	Tree right;
	
	class BSTIterator implements Iterator{
		private Tree tree;
		Stack<Tree> st;
		private void populateStack(Stack<Tree> st,Tree root)
		{
			 if(root==null) return;
			populateStack(st,root.right);
			st.push(root);
			populateStack(st,root.left);
 		}
		private BSTIterator(Tree tree){
			this.tree = tree;
			st=new Stack<Tree>();
			populateStack(st,this.tree);
		}
		@Override
		public boolean hasNext() {
			// TODO Auto-generated method stub
			return !st.isEmpty();
		}

		@Override
		public Tree next() {
			// TODO Auto-generated method stub
			return st.pop();
		}

		@Override
		public void remove() {
			// TODO Auto-generated method stub
			
		}
		
	}
	public BSTIterator iterator(){

		return new BSTIterator(this);
	}
//makes a binary tree out of an array

	public static Tree makeTree(int[] ar,int st,int en)
	{
		if(st>en) return null;
		int mid = (st+en)/2;
		Node root= new Node(ar[mid]);
		Tree tree = new Tree();
		tree.root=root;
		tree.left=makeTree(ar,st,mid-1);
		tree.right = makeTree(ar,mid+1,en);
		return tree;
	}
	public static void main(String[] args)
	{
		
		int[] a = {1,2,3,4,7,8,9,15,19,20,24};
		
		Tree tree = Tree.makeTree(a,0,a.length-1);
		
		for(Tree t:tree)
		{
			System.out.println(t.root.n);
		}
		
	}
	
}

 

answered Oct 27, 2015 by Birdie9
# Definition for a  binary tree node
class TreeNode:
     def __init__(self, x):
         self.val = x
         self.left = None
         self.right = None

class BSTIterator:
    # @param root, a binary search tree's root node
    def __init__(self, root):
        self.mystack = []
        self.pushem(root)
    # @return a boolean, whether we have a next smallest number
    def hasNext(self):
        if len(self.mystack)==0:
            return False
        return True

    # @return an integer, the next smallest number
    def next(self):
        temp = self.mystack[-1]
        self.mystack.pop()
        if temp.right:
         self.pushem(temp.right)
        return temp.val
    def pushem(self,A):
        while(A):
            self.mystack.append(A)
            A=A.left
        
# Your BSTIterator will be called like this:
# i = BSTIterator(root)
# while i.hasNext(): print i.next(),

 

answered Sep 9, 2016 by Vashisht
...