Cartesian tree from inorder traversal | Segment Tree

Given an in-order traversal of a cartesian tree, the task is to build the entire tree from it.

Examples:

Input: arr[] = {1, 5, 3}
Output: 1 5 3
  5
 / \
1   3

Input: arr[] = {3, 7, 4, 8}
Output: 3 7 4 8
     8
    /
   7
  / \
 3   4

Approach: We have already seen an algorithm here that takes O(NlogN) time on an average but can get to O(N2) in the worst case.



In this article, we will see how to build the cartesian in worst case running time of O(Nlog(N)). For this, we will use segment-tree to answer range-max queries.

Below will be our recursive algorithm on range {L, R}:

  1. Find the maximum in this range {L, R} using range-max query on the segment-tree. Let’s say ‘M’ is index the maximum in the range.
  2. Pick up ‘arr[M]’ as the value for current node and create a node with this value.
  3. Solve for range {L, M-1} and {M+1, R}.
  4. Set the node returned by {L, M-1} as the left child of current node and {M+1, R} as the right child.

Below is the implementation of the above approach:

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ implementation of the approach
#include <bits/stdc++.h>
using namespace std;
  
#define maxLen 30
  
// Node of the BST
struct node {
    int data;
    node* left;
    node* right;
    node(int data)
    {
        left = NULL;
        right = NULL;
        this->data = data;
    }
};
  
// Array to store segment tree
int segtree[maxLen * 3];
  
// Function to create segment-tree to answer
// range-max query
int buildTree(int l, int r, int i, int* arr)
{
    // Base case
    if (l == r) {
        segtree[i] = l;
        return l;
    }
  
    // Maximum index in left range
    int l1 = buildTree(l, (l + r) / 2,
                       2 * i + 1, arr);
  
    // Maximum index in right range
    int r1 = buildTree((l + r) / 2 + 1,
                       r, 2 * i + 2, arr);
  
    // If value at l1 > r1
    if (arr[l1] > arr[r1])
        segtree[i] = l1;
  
    // Else
    else
        segtree[i] = r1;
  
    // Returning the maximum in range
    return segtree[i];
}
  
// Function to answer range max query
int rangeMax(int l, int r, int rl,
             int rr, int i, int* arr)
{
  
    // Base cases
    if (r < rl || l > rr)
        return -1;
    if (l >= rl and r <= rr)
        return segtree[i];
  
    // Maximum in left range
    int l1 = rangeMax(l, (l + r) / 2, rl,
                      rr, 2 * i + 1, arr);
  
    // Maximum in right range
    int r1 = rangeMax((l + r) / 2 + 1, r,
                      rl, rr, 2 * i + 2, arr);
  
    // l1 = -1 means left range
    // was out-side required range
    if (l1 == -1)
        return r1;
    if (r1 == -1)
        return l1;
  
    // Returning the maximum
    // among two ranges
    if (arr[l1] > arr[r1])
        return l1;
    else
        return r1;
}
  
// Function to print the inorder
// traversal of the binary tree
void inorder(node* curr)
{
  
    // Base case
    if (curr == NULL)
        return;
  
    // Traversing the left sub-tree
    inorder(curr->left);
  
    // Printing current node
    cout << curr->data << " ";
  
    // Traversing the right sub-tree
    inorder(curr->right);
}
  
// Function to build cartesian tree
node* createCartesianTree(int l, int r, int* arr, int n)
{
    // Base case
    if (r < l)
        return NULL;
  
    // Maximum in the range
    int m = rangeMax(0, n - 1, l, r, 0, arr);
  
    // Creating current node
    node* curr = new node(arr[m]);
  
    // Creating left sub-tree
    curr->left = createCartesianTree(l, m - 1, arr, n);
  
    // Creating right sub-tree
    curr->right = createCartesianTree(m + 1, r, arr, n);
  
    // Returning current node
    return curr;
}
  
// Driver code
int main()
{
    // In-order traversal of cartesian tree
    int arr[] = { 8, 11, 21, 100, 5, 70, 55 };
  
    // Size of the array
    int n = sizeof(arr) / sizeof(int);
  
    // Building the segment tree
    buildTree(0, n - 1, 0, arr);
  
    // Building and printing cartesian tree
    inorder(createCartesianTree(0, n - 1, arr, n));
}
chevron_right

filter_none

edit
close

play_arrow

link
brightness_4
code

// Java implementation of the approach
import java.util.*;
  
class GFG
{
static int maxLen = 30;
  
// Node of the BST
static class node
{
    int data;
    node left;
    node right;
    node(int data)
    {
        left = null;
        right = null;
        this.data = data;
    }
};
  
// Array to store segment tree
static int segtree[] = new int[maxLen * 3];
  
// Function to create segment-tree to answer
// range-max query
static int buildTree(int l, int r, 
                     int i, int[] arr)
{
    // Base case
    if (l == r) 
    {
        segtree[i] = l;
        return l;
    }
  
    // Maximum index in left range
    int l1 = buildTree(l, (l + r) / 2,
                       2 * i + 1, arr);
  
    // Maximum index in right range
    int r1 = buildTree((l + r) / 2 + 1,
                        r, 2 * i + 2, arr);
  
    // If value at l1 > r1
    if (arr[l1] > arr[r1])
        segtree[i] = l1;
  
    // Else
    else
        segtree[i] = r1;
  
    // Returning the maximum in range
    return segtree[i];
}
  
// Function to answer range max query
static int rangeMax(int l, int r, int rl,
                    int rr, int i, int[] arr)
{
  
    // Base cases
    if (r < rl || l > rr)
        return -1;
    if (l >= rl && r <= rr)
        return segtree[i];
  
    // Maximum in left range
    int l1 = rangeMax(l, (l + r) / 2, rl,
                      rr, 2 * i + 1, arr);
  
    // Maximum in right range
    int r1 = rangeMax((l + r) / 2 + 1, r,
                       rl, rr, 2 * i + 2, arr);
  
    // l1 = -1 means left range
    // was out-side required range
    if (l1 == -1)
        return r1;
    if (r1 == -1)
        return l1;
  
    // Returning the maximum
    // among two ranges
    if (arr[l1] > arr[r1])
        return l1;
    else
        return r1;
}
  
// Function to print the inorder
// traversal of the binary tree
static void inorder(node curr)
{
  
    // Base case
    if (curr == null)
        return;
  
    // Traversing the left sub-tree
    inorder(curr.left);
  
    // Printing current node
    System.out.print(curr.data + " ");
  
    // Traversing the right sub-tree
    inorder(curr.right);
}
  
// Function to build cartesian tree
static node createCartesianTree(int l, int r,
                                int[] arr, int n)
{
    // Base case
    if (r < l)
        return null;
  
    // Maximum in the range
    int m = rangeMax(0, n - 1, l, r, 0, arr);
  
    // Creating current node
    node curr = new node(arr[m]);
  
    // Creating left sub-tree
    curr.left = createCartesianTree(l, m - 1, arr, n);
  
    // Creating right sub-tree
    curr.right = createCartesianTree(m + 1, r, arr, n);
  
    // Returning current node
    return curr;
}
  
// Driver code
public static void main(String args[])
{
    // In-order traversal of cartesian tree
    int arr[] = { 8, 11, 21, 100, 5, 70, 55 };
  
    // Size of the array
    int n = arr.length;
  
    // Building the segment tree
    buildTree(0, n - 1, 0, arr);
  
    // Building && printing cartesian tree
    inorder(createCartesianTree(0, n - 1, arr, n));
}
}
  
// This code is contributed by Arnab Kundu
chevron_right

filter_none

edit
close

play_arrow

link
brightness_4
code

// C# implementation of the approach
using System;
  
class GFG 
    static int maxLen = 30; 
      
    // Node of the BST 
    public class node 
    
        public int data; 
        public node left; 
        public node right; 
        public node(int data) 
        
            left = null
            right = null
            this.data = data; 
        
    }; 
      
    // Array to store segment tree 
    static int []segtree = new int[maxLen * 3]; 
      
    // Function to create segment-tree to answer 
    // range-max query 
    static int buildTree(int l, int r, 
                         int i, int[] arr) 
    
        // Base case 
        if (l == r) 
        
            segtree[i] = l; 
            return l; 
        
      
        // Maximum index in left range 
        int l1 = buildTree(l, (l + r) / 2, 
                           2 * i + 1, arr); 
      
        // Maximum index in right range 
        int r1 = buildTree((l + r) / 2 + 1, 
                            r, 2 * i + 2, arr); 
      
        // If value at l1 > r1 
        if (arr[l1] > arr[r1]) 
            segtree[i] = l1; 
      
        // Else 
        else
            segtree[i] = r1; 
      
        // Returning the maximum in range 
        return segtree[i]; 
    
      
    // Function to answer range max query 
    static int rangeMax(int l, int r, int rl, 
                        int rr, int i, int[] arr) 
    
      
        // Base cases 
        if (r < rl || l > rr) 
            return -1; 
        if (l >= rl && r <= rr) 
            return segtree[i]; 
      
        // Maximum in left range 
        int l1 = rangeMax(l, (l + r) / 2, rl, 
                          rr, 2 * i + 1, arr); 
      
        // Maximum in right range 
        int r1 = rangeMax((l + r) / 2 + 1, r, 
                           rl, rr, 2 * i + 2, arr); 
      
        // l1 = -1 means left range 
        // was out-side required range 
        if (l1 == -1) 
            return r1; 
        if (r1 == -1) 
            return l1; 
      
        // Returning the maximum 
        // among two ranges 
        if (arr[l1] > arr[r1]) 
            return l1; 
        else
            return r1; 
    
      
    // Function to print the inorder 
    // traversal of the binary tree 
    static void inorder(node curr) 
    
      
        // Base case 
        if (curr == null
            return
      
        // Traversing the left sub-tree 
        inorder(curr.left); 
      
        // Printing current node 
        Console.Write(curr.data + " "); 
      
        // Traversing the right sub-tree 
        inorder(curr.right); 
    
      
    // Function to build cartesian tree 
    static node createCartesianTree(int l, int r, 
                                    int[] arr, int n) 
    
        // Base case 
        if (r < l) 
            return null
      
        // Maximum in the range 
        int m = rangeMax(0, n - 1, l, r, 0, arr); 
      
        // Creating current node 
        node curr = new node(arr[m]); 
      
        // Creating left sub-tree 
        curr.left = createCartesianTree(l, m - 1,
                                         arr, n); 
      
        // Creating right sub-tree 
        curr.right = createCartesianTree(m + 1, r, 
                                          arr, n); 
      
        // Returning current node 
        return curr; 
    
      
    // Driver code 
    public static void Main() 
    
        // In-order traversal of cartesian tree 
        int []arr = { 8, 11, 21, 100, 5, 70, 55 }; 
      
        // Size of the array 
        int n = arr.Length; 
      
        // Building the segment tree 
        buildTree(0, n - 1, 0, arr); 
      
        // Building && printing cartesian tree 
        inorder(createCartesianTree(0, n - 1, arr, n)); 
    
}
  
// This code is contributed by AnkitRai01 
chevron_right

Output:
8 11 21 100 5 70 55

Time complexity: O(NlogN)




Check out this Author's contributed articles.

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.



Improved By : andrew1234, AnkitRai01



Article Tags :