Print BST keys in given Range | O(1) Space

Given two values n1 and n2 (where n1 < n2) and a root pointer to a Binary Search Tree. Print all the keys of tree in range n1 to n2. i.e. print all nodes n such that n1<=n<=n2 and n is a key of given BST. Print all the keys in increasing order.

Prerequisites : Morris traversal | Threaded binary trees

Inorder traversal uses recursion or stack/queue which consumes O(n) space. But there is one efficient way to do inorder tree traversal using Morris Traversal which is based in Threaded Binary trees. Morris traversal uses no recursion or stack/queue and simply stores some important information in the wasted NULL pointers. Morris traversal consumes constant extra memory O(1) as it uses no recursion or stack/queue. Hence we will use Morris traversal to do inorder traversal in the algorithm presented in this tutorial to print keys of a BST in a given range, which is efficient memory wise.

The concept of Threaded Binary trees is simple that they store some useful information in the wasted NULL pointers. In a normal binary tree with n nodes, n+1 NULL pointers waste memory.

Approach : Morris Traversal is a very nice memory efficient technique to do tree traversal without using stack or recursion in constant memory O(1) based on Threaded Binary Trees. Morris traversal can be used in solving problems where inorder tree traversals are used especially in order statistics eg-Kth largest element in BST, Kth smallest in BST etc. Hence, this is where Morris traversal would come handy as a more efficient method to do inorder traversal in constant O(1) space without using any stack or recursion.

Algorithm

1) Initialize Current as root.

2) While current is not NULL :

  2.1) If current has no left child

   a) Check if current lies between n1 and n2.
      1)If so, then visit the current node.

   b)Otherwise, Move to the right child of current.

  3) Else, here we have 2 cases:
   a) Find the inorder predecessor of current node. 
      Inorder predecessor is the right most node 
      in the left subtree or left child itself.

   b) If the right child of the inorder predecessor is NULL:
      1) Set current as the right child of its inorder predecessor.
      2) Move current node to its left child.

   c) Else, if the threaded link between the current node 
      and it's inorder predecessor already exists :
      1) Set right pointer of the inorder predecessor as NULL.
      2) Again check if current node lies between n1 and n2.
        a)If so, then visit the current node.
      
      3)Now move current to it's right child.

Below is the implementation of above approach.

C++

filter_none

edit
close

play_arrow

link
brightness_4
code

// CPP code to print BST keys in given Range in 
// constant space using Morris traversal.
#include <iostream>
  
using namespace std;
  
struct node {
  
    int data;
    struct node *left, *right;
};
  
// Function to print the keys in range
void RangeTraversal(node* root, 
                    int n1, int n2)
{
    if (!root)
        return;
  
    node* curr = root;
  
    while (curr) {
  
        if (curr->left == NULL) 
        {
            // check if current node 
            // lies between n1 and n2
            if (curr->data <= n2 && 
                curr->data >= n1) 
            {
                cout << curr->data << " ";
            }
  
            curr = curr->right;
        }
  
        else {
            node* pre = curr->left;
            // finding the inorder predecessor-
            // inorder predecessor is the right
            // most in left subtree or the left 
            // child, i.e in BST it is the 
            // maximum(right most) in left subtree.
            while (pre->right != NULL && 
                   pre->right != curr)
                        pre = pre->right;
  
            if (pre->right == NULL) 
            {
                pre->right = curr;
                curr = curr->left;
            }
  
            else {
                pre->right = NULL;
  
                // check if current node lies 
                // between n1 and n2
                if (curr->data <= n2 && 
                    curr->data >= n1) 
                {
                    cout << curr->data << " ";
                }
  
                curr = curr->right;
            }
        }
    }
}
  
// Helper function to create a new node
node* newNode(int data)
{
    node* temp = new node;
    temp->data = data;
    temp->right = temp->left = NULL;
  
    return temp;
}
  
// Driver Code
int main()
{
  
    /* Constructed binary tree is
          4
        /   \
       2     7
     /  \   /  \
    1    3  6    10
*/
  
    node* root = newNode(4);
    root->left = newNode(2);
    root->right = newNode(7);
    root->left->left = newNode(1);
    root->left->right = newNode(3);
    root->right->left = newNode(6);
    root->right->right = newNode(10);
  
    RangeTraversal(root, 4, 12);
      
    return 0;
}

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// Java code to print BST keys in given Range in 
// constant space using Morris traversal. 
class GfG { 
  
static class node { 
  
    int data; 
    node left, right; 
}
  
// Function to print the keys in range 
static void RangeTraversal(node root, int n1, int n2) 
    if (root == null
        return
  
    node curr = root; 
  
    while (curr != null) { 
  
        if (curr.left == null
        
            // check if current node 
            // lies between n1 and n2 
            if (curr.data <= n2 && curr.data >= n1) 
            
                System.out.print(curr.data + " "); 
            
  
            curr = curr.right; 
        
  
        else
            node pre = curr.left; 
            // finding the inorder predecessor- 
            // inorder predecessor is the right 
            // most in left subtree or the left 
            // child, i.e in BST it is the 
            // maximum(right most) in left subtree. 
            while (pre.right != null && pre.right != curr) 
                pre = pre.right; 
  
            if (pre.right == null
            
                pre.right = curr; 
                curr = curr.left; 
            
  
            else
                pre.right = null
  
                // check if current node lies 
                // between n1 and n2 
                if (curr.data <= n2 && curr.data >= n1) 
                
                    System.out.print(curr.data + " "); 
                
  
                curr = curr.right; 
            
        
    
  
// Helper function to create a new node 
static node newNode(int data) 
    node temp = new node(); 
    temp.data = data; 
    temp.right = null;
    temp.left = null
  
    return temp; 
  
// Driver Code 
public static void main(String[] args) 
  
    /* Constructed binary tree is 
        
        / \ 
    2     7 
    / \ / \ 
    1 3 6 10 
*/
  
    node root = newNode(4); 
    root.left = newNode(2); 
    root.right = newNode(7); 
    root.left.left = newNode(1); 
    root.left.right = newNode(3); 
    root.right.left = newNode(6); 
    root.right.right = newNode(10); 
  
    RangeTraversal(root, 4, 12); 
      

chevron_right


Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

# Python3 code to print BST keys in given Range 
# in constant space using Morris traversal.
  
# Helper function to create a new node 
class newNode: 
  
    # Constructor to create a new node 
    def __init__(self, data): 
        self.data = data 
        self.left = None
        self.right = None
  
# Function to print the keys in range 
def RangeTraversal(root, n1, n2):
    if root == None
        return
  
    curr = root 
    while curr:
        if curr.left == None:
              
            # check if current node lies 
            # between n1 and n2 
            if curr.data <= n2 and curr.data >= n1:
                print(curr.data, end = " ")
            curr = curr.right
        else:
            pre = curr.left 
              
            # finding the inorder predecessor- 
            # inorder predecessor is the right 
            # most in left subtree or the left 
            # child, i.e in BST it is the 
            # maximum(right most) in left subtree. 
            while (pre.right != None and 
                   pre.right != curr):
                pre = pre.right
                          
            if pre.right == None:
                pre.right = curr; 
                curr = curr.left
            else:
                pre.right = None
  
                # check if current node lies 
                # between n1 and n2 
                if curr.data <= n2 and curr.data >= n1:
                    print(curr.data, end = " ")
                curr = curr.right
  
# Driver Code 
if __name__ == '__main__':
  
    # Constructed binary tree is 
    #        4 
    #      / \ 
    #     2      7 
    #    / \ / \ 
    #   1  3 6 10 
    root = newNode(4
    root.left = newNode(2
    root.right = newNode(7)
    root.left.left = newNode(1)
    root.left.right = newNode(3
    root.right.left = newNode(6)
    root.right.right = newNode(10
  
    RangeTraversal(root, 4, 12)     
      
# This code is contributed by PranchalK

chevron_right


C#

filter_none

edit
close

play_arrow

link
brightness_4
code

// C# code to print BST keys in given Range in 
// constant space using Morris traversal. 
using System;
  
public class GfG 
  
public class node 
  
    public int data; 
    public node left, right; 
  
// Function to print the keys in range 
static void RangeTraversal(node root, int n1, int n2) 
    if (root == null
        return
  
    node curr = root; 
  
    while (curr != null)
    
  
        if (curr.left == null
        
            // check if current node 
            // lies between n1 and n2 
            if (curr.data <= n2 && curr.data >= n1) 
            
                Console.Write(curr.data + " "); 
            
  
            curr = curr.right; 
        
  
        else 
        
            node pre = curr.left; 
              
            // finding the inorder predecessor- 
            // inorder predecessor is the right 
            // most in left subtree or the left 
            // child, i.e in BST it is the 
            // maximum(right most) in left subtree. 
            while (pre.right != null && pre.right != curr) 
                pre = pre.right; 
  
            if (pre.right == null
            
                pre.right = curr; 
                curr = curr.left; 
            
  
            else 
            
                pre.right = null
  
                // check if current node lies 
                // between n1 and n2 
                if (curr.data <= n2 && curr.data >= n1) 
                
                    Console.Write(curr.data + " "); 
                
  
                curr = curr.right; 
            
        
    
  
// Helper function to create a new node 
static node newNode(int data) 
    node temp = new node(); 
    temp.data = data; 
    temp.right = null
    temp.left = null
  
    return temp; 
  
// Driver Code 
public static void Main(String[] args) 
  
    /* Constructed binary tree is 
        
        / \ 
    2 7 
    / \ / \ 
    1 3 6 10 
*/
  
    node root = newNode(4); 
    root.left = newNode(2); 
    root.right = newNode(7); 
    root.left.left = newNode(1); 
    root.left.right = newNode(3); 
    root.right.left = newNode(6); 
    root.right.right = newNode(10); 
  
    RangeTraversal(root, 4, 12); 
  
// This code has been contributed by 29AjayKumar

chevron_right


Output:

4 6 7 10

Time Complexity : O(n)
Auxiliary Space : O(1)



My Personal Notes arrow_drop_up

A technologist who loves exploring new technologies Passionate and interests in cloud computing and virtualization technologies Also a data nerd and a part time writer who loves writing

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.