Given a Binary Tree and two numbers P and K, the task is to print the K Inorder Successor of the given number P from the Binary tree in constant space.
Examples:
Input: Tree:
1 / \ 12 11 / / \ 3 4 13 \ / 15 9P = 12, K = 4
Output: 1 4 15 11
Explanation:
Inorder traversal: 3 12 1 4 15 11 9 13
The 4 Inorder Successor of a node 12 are {1, 4, 15, 11}
Input: Tree:
5 / \ 21 77 / \ \ 61 16 36 \ / 10 3 / 23P = 23, K = 3
Output: 10 5 77
Explanation:
Inorder traversal: 61 21 16 23 10 5 77 3 36
The 3 Inorder Successor Of a node 23 are {10, 5, 77}.
Approach:
In order to solve this problem, we are using the Morris Inorder Traversal of a Binary Tree to avoid the use of any extra space. Search for the node 'P' while generating the inorder sequence. Once found, print the next K nodes that appear in the inorder sequence.
Below is the implementation of the above approach:
// C++ implementation to print K Inorder
// Successor of the Binary Tree
// without using extra space
#include <bits/stdc++.h>
using namespace std;
/* A binary tree Node has data,
a pointer to left child
and a pointer to right child */
struct tNode {
int data;
struct tNode* left;
struct tNode* right;
};
/* Function to traverse the
binary tree without recursion and
without stack */
void MorrisTraversal(struct tNode* root,
int p, int k)
{
struct tNode *current, *pre;
if (root == NULL)
return;
bool flag = false;
current = root;
while (current != NULL) {
// Check if the left child exists
if (current->left == NULL) {
if (flag == true) {
cout << current->data
<< " ";
k--;
}
if (current->data == p)
flag = true;
// Check if K is 0
if (k == 0)
flag = false;
// Move current to its right
current = current->right;
}
else {
// Find the inorder predecessor
// of current
pre = current->left;
while (pre->right != NULL
&& pre->right != current)
pre = pre->right;
/* Make current as the right
child of its inorder
predecessor */
if (pre->right == NULL) {
pre->right = current;
current = current->left;
}
/* Revert the changes made in the
'if' part to restore the original
tree i.e., fix the right child
of predecessor */
else {
pre->right = NULL;
if (flag == true) {
cout << current->data
<< " ";
k--;
}
if (current->data == p)
flag = true;
if (k == 0)
flag = false;
current = current->right;
}
}
}
}
/* Function that allocates
a new Node with the
given data and NULL left
and right pointers. */
struct tNode* newtNode(int data)
{
struct tNode* node = new tNode;
node->data = data;
node->left = NULL;
node->right = NULL;
return (node);
}
/* Driver code*/
int main()
{
struct tNode* root = newtNode(1);
root->left = newtNode(12);
root->right = newtNode(11);
root->left->left = newtNode(3);
root->right->left = newtNode(4);
root->right->right = newtNode(13);
root->right->left->right = newtNode(15);
root->right->right->left = newtNode(9);
int p = 12;
int k = 4;
MorrisTraversal(root, p, k);
return 0;
}
// Java implementation to print K Inorder
// Successor of the Binary Tree
// without using extra space
// A binary tree Node has data,
// a pointer to left child
// and a pointer to right child
class tNode
{
int data;
tNode left, right;
tNode(int item)
{
data = item;
left = right = null;
}
}
class BinaryTree{
tNode root;
// Function to traverse a binary tree
// without recursion and without stack
void MorrisTraversal(tNode root, int p, int k)
{
tNode current, pre;
if (root == null)
return;
boolean flag = false;
current = root;
while (current != null)
{
if (current.left == null)
{
if (flag == true)
{
System.out.print(current.data + " ");
k--;
}
if (current.data == p)
{
flag = true;
}
if (k == 0)
{
flag = false;
}
current = current.right;
}
else
{
// Find the inorder predecessor
// of current
pre = current.left;
while (pre.right != null &&
pre.right != current)
pre = pre.right;
// Make current as right child of
// its inorder predecessor
if (pre.right == null)
{
pre.right = current;
current = current.left;
}
// Revert the changes made in the
// 'if' part to restore the original
// tree i.e., fix the right child of
// predecessor
else
{
pre.right = null;
if (flag == true)
{
System.out.print(current.data + " ");
k--;
}
if (current.data == p)
{
flag = true;
}
if (k == 0)
{
flag = false;
}
current = current.right;
}
}
}
}
// Driver code
public static void main(String args[])
{
BinaryTree tree = new BinaryTree();
tree.root = new tNode(1);
tree.root.left = new tNode(12);
tree.root.right = new tNode(11);
tree.root.left.left = new tNode(3);
tree.root.right.left = new tNode(4);
tree.root.right.right = new tNode(13);
tree.root.right.left.right = new tNode(15);
tree.root.right.right.left = new tNode(9);
int p = 12;
int k = 4;
tree.MorrisTraversal(tree.root, p, k);
}
}
// This code is contributed by MOHAMMAD MUDASSIR
# Python3 implementation to print K Inorder
# Successor of the Binary Tree
# without using extra space
''' A binary tree Node has data,
a pointer to left child
and a pointer to right child '''
class tNode:
def __init__(self, data):
self.data = data
self.left = None
self.right = None
''' Function to traverse the
binary tree without recursion and
without stack '''
def MorrisTraversal(root, p, k):
current = None
pre = None
if (root == None):
return;
flag = False;
current = root;
while (current != None):
# Check if the left child exists
if (current.left == None):
if (flag == True):
print(current.data, end = ' ')
k -= 1
if (current.data == p):
flag = True;
# Check if K is 0
if (k == 0):
flag = False;
# Move current to its right
current = current.right;
else:
# Find the inorder predecessor
# of current
pre = current.left
while (pre.right != None and pre.right != current):
pre = pre.right;
# Make current as the right
#child of its inorder predecessor
if(pre.right == None):
pre.right = current;
current = current.left;
# Revert the changes made in the
# 'if' part to restore the original
# tree i.e., fix the right child
# of predecessor
else:
pre.right = None;
if (flag == True):
print(current.data, end = ' ')
k -= 1
if (current.data == p):
flag = True;
if (k == 0):
flag = False;
current = current.right;
''' Function that allocates
a new Node with the
given data and None left
and right pointers. '''
def newtNode(data):
node = tNode(data);
return (node);
# Driver code
if __name__=='__main__':
root = newtNode(1);
root.left = newtNode(12);
root.right = newtNode(11);
root.left.left = newtNode(3);
root.right.left = newtNode(4);
root.right.right = newtNode(13);
root.right.left.right = newtNode(15);
root.right.right.left = newtNode(9);
p = 12;
k = 4;
MorrisTraversal(root, p, k);
# This code is contributed by rutvik_56
// C# program to print inorder traversal
// without recursion and stack
using System;
// A binary tree Node has data,
// pointer to left child and a
// pointer to right child
class BinaryTree{
tNode root;
public class tNode
{
public int data;
public tNode left, right;
public tNode(int item)
{
data = item;
left = right = null;
}
}
// Function to traverse binary tree without
// recursion and without stack
void MorrisTraversal(tNode root, int p, int k)
{
tNode current, pre;
if (root == null)
return;
current = root;
bool flag = false;
while (current != null)
{
if (current.left == null)
{
if (flag == true)
{
Console.Write(current.data + " ");
k--;
}
if (current.data == p)
{
flag = true;
}
if (k == 0)
{
flag = false;
}
current = current.right;
}
else
{
// Find the inorder predecessor
// of current
pre = current.left;
while (pre.right != null &&
pre.right != current)
pre = pre.right;
// Make current as right child
// of its inorder predecessor
if (pre.right == null)
{
pre.right = current;
current = current.left;
}
// Revert the changes made in
// if part to restore the original
// tree i.e., fix the right child
// of predecessor
else
{
pre.right = null;
if (flag == true)
{
Console.Write(current.data + " ");
k--;
}
if (current.data == p)
{
flag = true;
}
if (k == 0)
{
flag = false;
}
current = current.right;
}
}
}
}
// Driver code
public static void Main(String []args)
{
BinaryTree tree = new BinaryTree();
tree.root = new tNode(1);
tree.root.left = new tNode(12);
tree.root.right = new tNode(11);
tree.root.left.left = new tNode(3);
tree.root.right.left = new tNode(4);
tree.root.right.right = new tNode(13);
tree.root.right.left.right = new tNode(15);
tree.root.right.right.left = new tNode(9);
int p = 12;
int k = 4;
tree.MorrisTraversal(tree.root, p, k);
}
}
// This code is contributed by MOHAMMAD MUDASSIR
<script>
// Javascript implementation to print K Inorder
// Successor of the Binary Tree
// without using extra space
// A binary tree Node has data,
// a pointer to left child
// and a pointer to right child
class tNode
{
constructor(item) {
this.left = null;
this.right = null;
this.data = item;
}
}
let root;
// Function to traverse a binary tree
// without recursion and without stack
function MorrisTraversal(root, p, k)
{
let current, pre;
if (root == null)
return;
let flag = false;
current = root;
while (current != null)
{
if (current.left == null)
{
if (flag == true)
{
document.write(current.data + " ");
k--;
}
if (current.data == p)
{
flag = true;
}
if (k == 0)
{
flag = false;
}
current = current.right;
}
else
{
// Find the inorder predecessor
// of current
pre = current.left;
while (pre.right != null &&
pre.right != current)
pre = pre.right;
// Make current as right child of
// its inorder predecessor
if (pre.right == null)
{
pre.right = current;
current = current.left;
}
// Revert the changes made in the
// 'if' part to restore the original
// tree i.e., fix the right child of
// predecessor
else
{
pre.right = null;
if (flag == true)
{
document.write(current.data + " ");
k--;
}
if (current.data == p)
{
flag = true;
}
if (k == 0)
{
flag = false;
}
current = current.right;
}
}
}
}
root = new tNode(1);
root.left = new tNode(12);
root.right = new tNode(11);
root.left.left = new tNode(3);
root.right.left = new tNode(4);
root.right.right = new tNode(13);
root.right.left.right = new tNode(15);
root.right.right.left = new tNode(9);
let p = 12;
let k = 4;
MorrisTraversal(root, p, k);
// This code is contributed by decode2207.
</script>
Output:
1 4 15 11
Time Complexity: The time complexity of the above code is O(n), as it traverses the whole tree once to print the k inorder successors of the given node. The time complexity is linear because the Morris Traversal algorithm traverses the tree in a single pass.
Auxiliary Space: The Auxiliary Space of the above code is O(1), as it does not use any extra space other than the variables used for traversing the tree.