Open In App

Binary Tree Iterator for Inorder Traversal

Improve
Improve
Like Article
Like
Save
Share
Report

Given a Binary Tree and an input array. The task is to create an Iterator that utilizes next() and hasNext() functions to perform Inorder traversal on the binary tree.

Examples:

Input:        8                          Input Array =  [next(), hasNext(), next(), next(), next(), hasNext(), next(), next(), hasNext()]
                /   \                
              3     9
           /   \                        
        2     4                                       
                 \ 
                  5     

Output: [2, true, 3, 4, 5, true, 8, 9, false]         
Explanation: According to in order traversal answer to the input array is calculated. 
Inorder traversal = {2, 3, 4, 5, 8, 9}

Input:     4                           Input Array = [hasNext(), next(), next(), hasNext()]
            /    \
          3      2
                    \
                     1 

Output: [true, 3, 4 true]           

 

Naive Approach: A way is needed to traverse back to the ancestor once we reach the leaf node of the binary tree. A Stack data structure can be used for this. 

Algorithm: 

Class is Instantiated

  1. initialize the stack
  2. set current node = root
  3. while current != NULL
    1. add current to stack
    2. current = current.left

hasNext() function

IF the stack is not empty

    return true

ELSE

    return false

next() function

  • IF stack is empty (or hasNext() returns false)
    • Throw an exception
  • ELSE
    • Initialize current = stack.top
    • Pop the element from the stack
    • If current.right != NULL
      • Initialize next = current->right
      • while next != NULL
        • add next to the stack
        • next = next.left
    • return current

Below is the implementation of above approach

C++




// CPP Program for above approach
#include <iostream>
#include <stack>
using namespace std;
 
// Structure of a Node
struct Node {
    int data;
    Node* left;
    Node* right;
};
 
// Utility function to create a new Node
Node* newNode(int data)
{
    Node* node = new Node;
    node->data = data;
    node->left = node->right = NULL;
    return node;
}
 
// Inorder Iterator class
class InorderIterator {
private:
    stack<Node*> traversal;
 
public:
    InorderIterator(Node* root)
    {
        moveLeft(root);
    }
 
    void moveLeft(Node* current)
    {
        while (current) {
            traversal.push(current);
            current = current->left;
        }
    }
 
    bool hasNext()
    {
        return !traversal.empty();
    }
 
    Node* next()
    {
        if (!hasNext())
            throw "No such element Exists";
 
        Node* current = traversal.top();
        traversal.pop();
 
        if (current->right)
            moveLeft(current->right);
 
        return current;
    }
};
 
// Driver Code
int main()
{
    Node* root = newNode(8);
    root->right = newNode(9);
    root->left = newNode(3);
    root->left->left = newNode(2);
    root->left->right = newNode(4);
    root->left->right->right = newNode(5);
 
    InorderIterator itr(root);
    try {
        cout << itr.next()->data << " ";
        cout << itr.hasNext() << " ";
        cout << itr.next()->data << " ";
        cout << itr.next()->data << " ";
        cout << itr.next()->data << " ";
        cout << itr.hasNext() << " ";
        cout << itr.next()->data << " ";
        cout << itr.next()->data << " ";
        cout << itr.hasNext() << " ";
    }
    catch (const char* msg) {
        cout << msg;
    }
    return 0;
}
 
// This code is contributed by adityamaharshi21


Java




// Java Program for above approach
import java.util.*;
 
// Structure of a Node
class Node {
    int data;
    Node left;
    Node right;
 
    Node(int data)
    {
        this.data = data;
        left = right = null;
    }
}
 
// Inorder Iterator class
class InorderIterator {
    private Stack<Node> traversal;
 
    InorderIterator(Node root)
    {
        traversal = new Stack<Node>();
        moveLeft(root);
    }
 
    private void moveLeft(Node current)
    {
        while (current != null) {
            traversal.push(current);
            current = current.left;
        }
    }
 
    public boolean hasNext()
    {
        return !traversal.isEmpty();
    }
 
    public Node next()
    {
        if (!hasNext())
            throw new NoSuchElementException();
 
        Node current = traversal.pop();
 
        if (current.right != null)
            moveLeft(current.right);
 
        return current;
    }
}
 
// Class to Test given set of inputs
class Test {
 
    // Driver Code
    public static void main(String args[])
    {
        Node root = new Node(8);
        root.right = new Node(9);
        root.left = new Node(3);
        root.left.left = new Node(2);
        root.left.right = new Node(4);
        root.left.right.right = new Node(5);
 
        InorderIterator itr = new InorderIterator(root);
        try {
            System.out.print(itr.next().data + " ");
            System.out.print(itr.hasNext() + " ");
            System.out.print(itr.next().data + " ");
            System.out.print(itr.next().data + " ");
            System.out.print(itr.next().data + " ");
            System.out.print(itr.hasNext() + " ");
            System.out.print(itr.next().data + " ");
            System.out.print(itr.next().data + " ");
            System.out.print(itr.hasNext() + " ");
        }
        catch (NoSuchElementException e) {
            System.out.print("No such element Exists");
        }
    }
}


Python




# Python Program for above approach
class Node:
    def __init__(self, data):
        self.data = data
        self.left = None
        self.right = None
 
# Inorder Iterator class
class InorderIterator:
    def __init__(self, root):
        self.traversal = []
        self.moveLeft(root)
 
    def moveLeft(self, current):
        while current != None:
            self.traversal.append(current)
            current = current.left
 
    def hasNext(self):
        return len(self.traversal) > 0
 
    def next(self):
        if not self.hasNext():
            raise Exception('No such element Exists')
 
        current = self.traversal.pop()
 
        if current.right != None:
            self.moveLeft(current.right)
 
        return current
 
# Class to Test given set of inputs
 
# Driver Code
root = Node(8)
root.right = Node(9)
root.left = Node(3)
root.left.left = Node(2)
root.left.right = Node(4)
root.left.right.right = Node(5)
 
itr = InorderIterator(root)
try:
    print(itr.next().data)
    print(itr.hasNext())
    print(itr.next().data)
    print(itr.next().data)
    print(itr.next().data)
    print(itr.hasNext())
    print(itr.next().data)
    print(itr.next().data)
    print(itr.hasNext())
except Exception as e:
    print("No such element Exists")
     
# This code is contributed by adityamaharshi21


C#




// C# code for the above approach
using System;
using System.Collections.Generic;
 
// Structure of a Node
class Node
{
  public int Data { get; set; }
  public Node Left { get; set; }
  public Node Right { get; set; }
 
  public Node(int data)
  {
    Data = data;
    Left = Right = null;
  }
}
 
// Inorder Iterator class
class InorderIterator
{
  private Stack<Node> traversal;
 
  public InorderIterator(Node root)
  {
    traversal = new Stack<Node>();
    MoveLeft(root);
  }
 
  private void MoveLeft(Node current)
  {
    while (current != null)
    {
      traversal.Push(current);
      current = current.Left;
    }
  }
 
  public bool HasNext()
  {
    return traversal.Count > 0;
  }
 
  public Node Next()
  {
    if (!HasNext())
      throw new InvalidOperationException("No more elements in the inorder traversal.");
 
    Node current = traversal.Pop();
 
    if (current.Right != null)
      MoveLeft(current.Right);
 
    return current;
  }
}
 
// Class to Test given set of inputs
class GFG
{
  // Driver Code
  static void Main(string[] args)
  {
    Node root = new Node(8);
    root.Right = new Node(9);
    root.Left = new Node(3);
    root.Left.Left = new Node(2);
    root.Left.Right = new Node(4);
    root.Left.Right.Right = new Node(5);
 
    InorderIterator itr = new InorderIterator(root);
    try
    {
      Console.Write(itr.Next().Data + " ");
      Console.Write(itr.HasNext() + " ");
      Console.Write(itr.Next().Data + " ");
      Console.Write(itr.Next().Data + " ");
      Console.Write(itr.Next().Data + " ");
      Console.Write(itr.HasNext() + " ");
      Console.Write(itr.Next().Data + " ");
      Console.Write(itr.Next().Data + " ");
      Console.Write(itr.HasNext() + " ");
    }
    catch (InvalidOperationException e)
    {
      Console.Write("No such element Exists");
    }
  }
}
 
// This code is contributed by Potta Lokesh


Javascript




// Javascript Program for above approach
class Node {
    constructor(data) {
        this.data = data;
        this.left = null;
        this.right = null;
    }
}
 
// Inorder Iterator class
class InorderIterator {
    constructor(root) {
        this.traversal = [];
        this.moveLeft(root);
    }
 
    moveLeft(current) {
        while (current != null) {
            this.traversal.push(current);
            current = current.left;
        }
    }
 
    hasNext() {
        return this.traversal.length > 0;
    }
 
    next() {
        if (!this.hasNext())
            throw new Error('No such element Exists');
 
        let current = this.traversal.pop();
 
        if (current.right != null)
            this.moveLeft(current.right);
 
        return current;
    }
}
 
// Class to Test given set of inputs
 
 
// Driver Code
let root = new Node(8);
root.right = new Node(9);
root.left = new Node(3);
root.left.left = new Node(2);
root.left.right = new Node(4);
root.left.right.right = new Node(5);
 
let itr = new InorderIterator(root);
try {
    console.log(itr.next().data + " ");
    console.log(itr.hasNext() + " ");
    console.log(itr.next().data + " ");
    console.log(itr.next().data + " ");
    console.log(itr.next().data + " ");
    console.log(itr.hasNext() + " ");
    console.log(itr.next().data + " ");
    console.log(itr.next().data + " ");
    console.log(itr.hasNext() + " ");
}
catch (e) {
    console.log("No such element Exists");
}
 
// This code is contributed by adityamaharshi21


Output

2 true 3 4 5 true 8 9 false 

Time Complexity: O(N), Where N is the number of nodes in the binary tree. 
Auxiliary Space: O(N), The Stack will hold all N elements in the worst case.

Efficient Approach: Morris Traversal can be used to solve this question using constant space. The idea behind morris traversal is to create a temporary link between a node and the right-most node in its left sub-tree so that the ancestor node can be backtracked. A reference of the ancestor node is set to the right child of the right-most node in its left sub-tree. 

Algorithm: 

Class is Instantiated 

Initialize current = root and rightMost = NULL

hasNext() function

IF current != NULL

   return true

ELSE

   return false

 

next() function

  • IF current = NULL ( or hasNext() returns false)
    • Throw an exception
  • ELSE
    • IF current.left = NULL
      • Initialize temp = current
      • current = current.right
      • return temp
    • ELSE
      • Initialize rightMost = current->left
      • while rightMost.right != NULL && rightMost.right != current
        • rightMost = rightMost.right
        • IF rightMost.right == NULL
          • rightMost.right = current
          • current = current.left
        • ELSE
          • temp = current
          • rightMost.right = null
          • current = current.right
          • return current
        • Call the function again

 

Below is the implementation of above approach.

 

C++




#include <iostream>
#include <stack>
 
struct Node {
    int data;
    Node *left, *right;
 
    Node(int data) {
        this->data = data;
        this->left = this->right = NULL;
    }
};
 
class InorderIterator {
private:
    Node *current, *rightMost;
public:
    InorderIterator(Node *root) {
        current = root;
        rightMost = NULL;
    }
 
    bool hasNext() { return current != NULL; }
 
    Node* next() {
        if (!hasNext()) {
            std::cout << "No such element exists" << std::endl;
            return NULL;
        }
 
        if (current->left == NULL) {
            Node *temp = current;
            current = current->right;
            return temp;
        }
 
        rightMost = current->left;
 
        while (rightMost->right != NULL
               && rightMost->right != current) {
            rightMost = rightMost->right;
        }
 
        if (rightMost->right == NULL) {
            rightMost->right = current;
            current = current->left;
        } else {
            rightMost->right = NULL;
            Node *temp = current;
            current = current->right;
            return temp;
        }
 
        return next();
    }
};
 
int main() {
    Node *root = new Node(8);
    root->right = new Node(9);
    root->left = new Node(3);
    root->left->left = new Node(2);
    root->left->right = new Node(4);
    root->left->right->right = new Node(5);
 
    InorderIterator itr(root);
    std::cout << itr.next()->data << " ";
    std::cout << itr.hasNext() << " ";
    std::cout << itr.next()->data << " ";
    std::cout << itr.next()->data << " ";
    std::cout << itr.next()->data << " ";
    std::cout << itr.hasNext() << " ";
    std::cout << itr.next()->data << " ";
    std::cout << itr.next()->data << " ";
    std::cout << itr.hasNext() << " ";
    return 0;
}
 
// This code is contributed by anskalyan3.


Java




// Java Program for above approach
import java.util.*;
 
// Structure of a Node
class Node {
    int data;
    Node left;
    Node right;
 
    Node(int data)
    {
        this.data = data;
        left = right = null;
    }
}
 
// Inorder Iterator class
class InorderIterator {
    private Node current, rightMost;
 
    InorderIterator(Node root)
    {
        current = root;
        rightMost = null;
    }
 
    public boolean hasNext() { return current != null; }
 
    public Node next()
    {
        if (!hasNext())
            throw new NoSuchElementException();
 
        if (current.left == null) {
            Node temp = current;
            current = current.right;
            return temp;
        }
 
        rightMost = current.left;
 
        while (rightMost.right != null
               && rightMost.right != current)
            rightMost = rightMost.right;
 
        if (rightMost.right == null) {
            rightMost.right = current;
            current = current.left;
        }
 
        else {
            rightMost.right = null;
            Node temp = current;
            current = current.right;
            return temp;
        }
 
        return next();
    }
}
 
class Test {
 
    // Driver Code
    public static void main(String args[])
    {
        Node root = new Node(8);
        root.right = new Node(9);
        root.left = new Node(3);
        root.left.left = new Node(2);
        root.left.right = new Node(4);
        root.left.right.right = new Node(5);
 
        InorderIterator itr = new InorderIterator(root);
        try {
            System.out.print(itr.next().data + " ");
            System.out.print(itr.hasNext() + " ");
            System.out.print(itr.next().data + " ");
            System.out.print(itr.next().data + " ");
            System.out.print(itr.next().data + " ");
            System.out.print(itr.hasNext() + " ");
            System.out.print(itr.next().data + " ");
            System.out.print(itr.next().data + " ");
            System.out.print(itr.hasNext() + " ");
        }
        catch (NoSuchElementException e) {
            System.out.print("No such element Exists");
        }
    }
}


Python




class Node:
    def __init__(self, data):
        self.data = data
        self.left = self.right = None
 
 
class InorderIterator:
    def __init__(self, root):
        self.current = root
        self.right_most = None
 
    def has_next(self):
        return self.current is not None
 
    def next(self):
        if not self.has_next():
            print("No such element exists")
            return None
 
        if self.current.left is None:
            temp = self.current
            self.current = self.current.right
            return temp
 
        self.right_most = self.current.left
 
        while self.right_most.right is not None and self.right_most.right != self.current:
            self.right_most = self.right_most.right
 
        if self.right_most.right is None:
            self.right_most.right = self.current
            self.current = self.current.left
        else:
            self.right_most.right = None
            temp = self.current
            self.current = self.current.right
            return temp
 
        return self.next()
 
 
root = Node(8)
root.right = Node(9)
root.left = Node(3)
root.left.left = Node(2)
root.left.right = Node(4)
root.left.right.right = Node(5)
 
itr = InorderIterator(root)
print(itr.next().data)
print(itr.has_next())
print(itr.next().data)
print(itr.next().data)
print(itr.next().data)
print(itr.has_next())
print(itr.next().data)
print(itr.next().data)
print(itr.has_next())


Javascript




// JavaScript program for above approach
class Node {
    constructor(data) {
        this.data = data;
        this.left = null;
        this.right = null;
    }
}
 
class InorderIterator {
    constructor(root) {
        this.current = root;
        this.rightMost = null;
    }
 
    hasNext() { return this.current != null; }
 
    next() {
        if (!this.hasNext())
            throw new Error("No such element Exists");
 
        if (this.current.left == null) {
            let temp = this.current;
            this.current = this.current.right;
            return temp;
        }
 
        this.rightMost = this.current.left;
 
        while (this.rightMost.right != null
               && this.rightMost.right != this.current)
            this.rightMost = this.rightMost.right;
 
        if (this.rightMost.right == null) {
            this.rightMost.right = this.current;
            this.current = this.current.left;
        }
 
        else {
            this.rightMost.right = null;
            let temp = this.current;
            this.current = this.current.right;
            return temp;
        }
 
        return this.next();
    }
}
 
let root = new Node(8);
root.right = new Node(9);
root.left = new Node(3);
root.left.left = new Node(2);
root.left.right = new Node(4);
root.left.right.right = new Node(5);
 
let itr = new InorderIterator(root);
try {
    console.log(itr.next().data + " ");
    console.log(itr.hasNext() + " ");
    console.log(itr.next().data + " ");
    console.log(itr.next().data + " ");
    console.log(itr.next().data + " ");
    console.log(itr.hasNext() + " ");
    console.log(itr.next().data + " ");
    console.log(itr.next().data + " ");
    console.log(itr.hasNext() + " ");
}
catch (e) {
    console.log("No such element Exists");
}
 
// This code is contributed by adityamaharshi21


C#




// C# Program for above approach
 
using System;
using System.Collections.Generic;
 
// Structure of a Node
public class Node {
    public int data;
    public Node left, right;
    public Node(int data)
    {
        this.data = data;
        left = right = null;
    }
}
 
// Inorder Iterator class
public class InorderIterator {
    private Node current, rightMost;
    public InorderIterator(Node root)
    {
        current = root;
        rightMost = null;
    }
 
    public bool HasNext() { return current != null; }
 
    public Node Next()
    {
        if (!HasNext())
            throw new Exception("No such element exists");
 
        if (current.left == null) {
            Node temp = current;
            current = current.right;
            return temp;
        }
 
        rightMost = current.left;
 
        while (rightMost.right != null
               && rightMost.right != current)
            rightMost = rightMost.right;
 
        if (rightMost.right == null) {
            rightMost.right = current;
            current = current.left;
        }
 
        else {
            rightMost.right = null;
            Node temp = current;
            current = current.right;
            return temp;
        }
 
        return Next();
    }
}
 
public class GFG {
 
    static public void Main()
    {
 
        // Code
        Node root = new Node(8);
        root.right = new Node(9);
        root.left = new Node(3);
        root.left.left = new Node(2);
        root.left.right = new Node(4);
        root.left.right.right = new Node(5);
 
        InorderIterator itr = new InorderIterator(root);
        try {
            Console.Write(itr.Next().data + " ");
            Console.Write(itr.HasNext() + " ");
            Console.Write(itr.Next().data + " ");
            Console.Write(itr.Next().data + " ");
            Console.Write(itr.Next().data + " ");
            Console.Write(itr.HasNext() + " ");
            Console.Write(itr.Next().data + " ");
            Console.Write(itr.Next().data + " ");
            Console.Write(itr.HasNext() + " ");
        }
        catch (Exception e) {
            Console.Write("No such element Exists");
        }
    }
}
 
// This code is contributed by karthik


 
 

Output

2 true 3 4 5 true 8 9 false 

 

Time Complexity: O(N), where N is the number of nodes in the binary tree. Although we are creating temporary links are created and nodes are traversed multiple times (at most 3 times), the time complexity is still linear.
Auxiliary Space: O(1)

 



Last Updated : 20 Feb, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads