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
\
5Output: [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
\
1Output: [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
- initialize the stack
- set current node = root
- while current != NULL
- add current to stack
- 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
// 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 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 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# 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 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.
#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 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");
}
}
}
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 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# 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)