Open In App

Van Emde Boas Tree – Set 3 | Successor and Predecessor

It is highly recommended to read the previous articles on Van Emde Boas Tree first.

Procedure for successor: 



See query for the successor of 0 the in below image: 



The below image represents the successor of 1 query over VEB tree containing key 1 & 2: 

Procedure for Predecessor: 

Below image represents query predecessor of key-2:  




#include <bits/stdc++.h>
using namespace std;
 
class Van_Emde_Boas {
 
public:
    int universe_size;
    int minimum;
    int maximum;
    Van_Emde_Boas* summary;
    vector<Van_Emde_Boas*> clusters;
 
    // Function to return cluster numbers
    // in which key is present
    int high(int x)
    {
        int div = ceil(sqrt(universe_size));
        return x / div;
    }
 
    // Function to return position of x in cluster
    int low(int x)
    {
        int mod = ceil(sqrt(universe_size));
        return x % mod;
    }
 
    // Function to return the index from
    // cluster number and position
    int generate_index(int x, int y)
    {
        int ru = ceil(sqrt(universe_size));
        return x * ru + y;
    }
 
    // Constructor
    Van_Emde_Boas(int size)
    {
        universe_size = size;
        minimum = -1;
        maximum = -1;
 
        // Base case
        if (size <= 2) {
            summary = nullptr;
            clusters = vector<Van_Emde_Boas*>(0, nullptr);
        }
        else {
            int no_clusters = ceil(sqrt(size));
 
            // Assigning VEB(sqrt(u)) to summary
            summary = new Van_Emde_Boas(no_clusters);
 
            // Creating array of VEB Tree pointers of size sqrt(u)
            clusters = vector<Van_Emde_Boas*>(no_clusters, nullptr);
 
            // Assigning VEB(sqrt(u)) to all its clusters
            for (int i = 0; i < no_clusters; i++) {
                clusters[i] = new Van_Emde_Boas(ceil(sqrt(size)));
            }
        }
    }
};
 
// Function to return the minimum value
// from the tree if it exists
int VEB_minimum(Van_Emde_Boas* helper)
{
    return (helper->minimum == -1 ? -1 : helper->minimum);
}
 
// Function to return the maximum value
// from the tree if it exists
int VEB_maximum(Van_Emde_Boas* helper)
{
    return (helper->maximum == -1 ? -1 : helper->maximum);
}
 
// Function to insert a key in the tree
void insert(Van_Emde_Boas* helper, int key)
{
    // If no key is present in the tree
    // then set both minimum and maximum
    // to the key (Read the previous article
    // for more understanding about it)
    if (helper->minimum == -1) {
        helper->minimum = key;
        helper->maximum = key;
    }
    else {
        if (key < helper->minimum) {
 
            // If the key is less than the current minimum
            // then swap it with the current minimum
            // because this minimum is actually
            // minimum of one of the internal cluster
            // so as we go deeper into the Van Emde Boas
            // we need to take that minimum to its real position
            // This concept is similar to "Lazy Propagation"
            swap(helper->minimum, key);
        }
 
        // Not base case then...
        if (helper->universe_size > 2) {
 
            // If no key is present in the cluster then insert key into
            // both cluster and summary
            if (VEB_minimum(helper->clusters[helper->high(key)]) == -1) {
                insert(helper->summary, helper->high(key));
 
                // Sets the minimum and maximum of cluster to the key
                // as no other keys are present we will stop at this level
                // we are not going deeper into the structure like
                // Lazy Propagation
                helper->clusters[helper->high(key)]->minimum = helper->low(key);
                helper->clusters[helper->high(key)]->maximum = helper->low(key);
            }
            else {
                // If there are other elements in the tree then recursively
                // go deeper into the structure to set attributes accordingly
                insert(helper->clusters[helper->high(key)], helper->low(key));
            }
        }
 
        // Sets the key as maximum it is greater than current maximum
        if (key > helper->maximum) {
            helper->maximum = key;
        }
    }
}
 
// Function that returns true if the
// key is present in the tree
bool isMember(Van_Emde_Boas* helper, int key)
{
 
    // If universe_size is less than the key
    // then we can not search the key so returns
    // false
    if (helper->universe_size < key) {
        return false;
    }
 
    // If at any point of our traversal
    // of the tree if the key is the minimum
    // or the maximum of the subtree, then
    // the key is present so returns true
    if (helper->minimum == key || helper->maximum == key) {
        return true;
    }
    else {
 
        // If after attending above condition,
        // if the size of the tree is 2 then
        // the present key must be
        // maximum or minimum of the tree if it
        // is not then it returns false because key
        // can not be present in the sub tree
        if (helper->universe_size == 2) {
            return false;
        }
        else {
 
            // Recursive call over the cluster
            // in which the key can be present
            // and also pass the new position of the key
            // i.e., low(key)
            return isMember(helper->clusters[helper->high(key)],
                            helper->low(key));
        }
    }
}
 
// Function to find the successor of the given key
int VEB_successor(Van_Emde_Boas* helper, int key)
{
 
    // Base case: If key is 0 and its successor
    // is present then return 1 else return null
    if (helper->universe_size == 2) {
 
        if (key == 0 && helper->maximum == 1) {
            return 1;
        }
        else {
            return -1;
        }
    }
 
    // If key is less then minimum then return minimum
    // because it will be successor of the key
    else if (helper->minimum != -1 && key < helper->minimum) {
 
        return helper->minimum;
    }
    else {
 
        // Find successor inside the cluster of the key
        // First find the maximum in the cluster
        int max_incluster = VEB_maximum(helper->clusters[helper->high(key)]);
 
        int offset{ 0 }, succ_cluster{ 0 };
 
        // If there is any key( maximum!=-1 ) present in the cluster then find
        // the successor inside of the cluster
        if (max_incluster != -1 && helper->low(key) < max_incluster) {
 
            offset = VEB_successor(helper->clusters[helper->high(key)],
                                   helper->low(key));
 
            return helper->generate_index(helper->high(key), offset);
        }
 
        // Otherwise look for the next cluster with at least one key present
        else {
 
            succ_cluster = VEB_successor(helper->summary, helper->high(key));
 
            // If there is no cluster with any key present
            // in summary then return null
            if (succ_cluster == -1) {
                return -1;
            }
 
            // Find minimum in successor cluster which will
            // be the successor of the key
            else {
 
                offset = VEB_minimum(helper->clusters[succ_cluster]);
 
                return helper->generate_index(succ_cluster, offset);
            }
        }
    }
}
 
// Function to find the predecessor of the given key
int VEB_predecessor(Van_Emde_Boas* helper, int key)
{
 
    // Base case: If the key is 1 and it's predecessor
    // is present then return 0 else return null
    if (helper->universe_size == 2) {
 
        if (key == 1 && helper->minimum == 0) {
            return 0;
        }
        else
            return -1;
    }
 
    // If the key is greater than maximum of the tree then
    // return key as it will be the predecessor of the key
    else if (helper->maximum != -1 && key > helper->maximum) {
 
        return helper->maximum;
    }
    else {
 
        // Find predecessor in the cluster of the key
        // First find minimum in the key to check whether any key
        // is present in the cluster
        int min_incluster = VEB_minimum(helper->clusters[helper->high(key)]);
 
        int offset{ 0 }, pred_cluster{ 0 };
 
        // If any key is present in the cluster then find predecessor in
        // the cluster
        if (min_incluster != -1 && helper->low(key) > min_incluster) {
 
            offset = VEB_predecessor(helper->clusters[helper->high(key)],
                                     helper->low(key));
 
            return helper->generate_index(helper->high(key), offset);
        }
 
        // Otherwise look for predecessor in the summary which
        // returns the index of predecessor cluster with any key present
        else {
 
            pred_cluster = VEB_predecessor(helper->summary, helper->high(key));
 
            // If no predecessor cluster then...
            if (pred_cluster == -1) {
 
                // Special case which is due to lazy propagation
                if (helper->minimum != -1 && key > helper->minimum) {
                    return helper->minimum;
                }
 
                else
                    return -1;
            }
 
            // Otherwise find maximum in the predecessor cluster
            else {
 
                offset = VEB_maximum(helper->clusters[pred_cluster]);
 
                return helper->generate_index(pred_cluster, offset);
            }
        }
    }
}
 
// Driver code
int main()
{
 
    Van_Emde_Boas* veb = new Van_Emde_Boas(8);
 
    // Inserting Keys
    insert(veb, 2);
    insert(veb, 3);
    insert(veb, 4);
    insert(veb, 6);
 
    // Queries
    cout << VEB_successor(veb, 2) << endl;
 
    cout << VEB_predecessor(veb, 6) << endl;
 
    cout << VEB_successor(veb, 4) << endl;
 
    return 0;
}




import java.util.*;
 
class Van_Emde_Boas {
 
    public int universe_size;
    public int minimum;
    public int maximum;
    public Van_Emde_Boas summary;
    public ArrayList<Van_Emde_Boas> clusters;
 
    public Van_Emde_Boas(int size)
    {
        universe_size = size;
        minimum = -1;
        maximum = -1;
 
        // Base case
        if (size <= 2) {
            summary = null;
            clusters = new ArrayList<Van_Emde_Boas>(0);
        }
        else {
            int no_clusters
                = (int)Math.ceil(Math.sqrt(size));
            summary = new Van_Emde_Boas(no_clusters);
 
            clusters
                = new ArrayList<Van_Emde_Boas>(no_clusters);
 
            for (int i = 0; i < no_clusters; i++) {
                clusters.add(new Van_Emde_Boas(
                    (int)Math.ceil(Math.sqrt(size))));
            }
        }
    }
 
    // Function to return cluster numbers
    // in which key is present
    public int high(int x)
    {
        int div = (int)Math.ceil(Math.sqrt(universe_size));
        return x / div;
    }
    // Function to return position of x in cluster
    public int low(int x)
    {
        int mod = (int)Math.ceil(Math.sqrt(universe_size));
        return x % mod;
    }
 
    // Function to return position of x in cluster
    public int generate_index(int x, int y)
    {
        int ru = (int)Math.ceil(Math.sqrt(universe_size));
        return x * ru + y;
    }
}
 
class Main {
 
    // Function to return the minimum value
    // from the tree if it exists
    public static int VEB_minimum(Van_Emde_Boas helper)
    {
        return (helper.minimum == -1 ? -1 : helper.minimum);
    }
 
    // Function to return the maximum value
    // from the tree if it exists
    public static int VEB_maximum(Van_Emde_Boas helper)
    {
        return (helper.maximum == -1 ? -1 : helper.maximum);
    }
 
    // Function to insert a key in the tree
    static void insert(Van_Emde_Boas helper, int key)
    {
 
        // If no key is present in the tree
        // then set both minimum and maximum
        // to the key (Read the previous article
        // for more understanding about it)
        if (helper.minimum == -1) {
            helper.minimum = key;
            helper.maximum = key;
        }
        else {
            // If the key is less than the current minimum
            // then swap it with the current minimum
            // because this minimum is actually
            // minimum of one of the internal cluster
            if (key < helper.minimum) {
                int temp = helper.minimum;
                helper.minimum = key;
                key = temp;
            }
 
            // Not base case then...
            if (helper.universe_size > 2) {
 
                // If no key is present in the cluster then
                // insert key into both cluster and summary
                if (VEB_minimum(helper.clusters.get(
                        helper.high(key)))
                    == -1) {
                    insert(helper.summary,
                           helper.high(key));
 
                    // Sets the minimum and maximum of
                    // cluster to the key as no other keys
                    // are present we will stop at this
                    // level
                    helper.clusters.get(helper.high(key))
                        .minimum
                        = helper.low(key);
                    helper.clusters.get(helper.high(key))
                        .maximum
                        = helper.low(key);
                }
                else {
                    // If there are other elements in the
                    // tree then recursively go deeper into
                    // the structure to set attributes
                    // accordingly
                    insert(helper.clusters.get(
                               helper.high(key)),
                           helper.low(key));
                }
            }
            // Sets the key as maximum it is greater than
            // current maximum
            if (key > helper.maximum) {
                helper.maximum = key;
            }
        }
    }
 
    // Function to find the successor of the given key
    public static int VEB_successor(Van_Emde_Boas helper,
                                    int key)
    {
        if (helper.universe_size == 2) {
            if (key == 0 && helper.maximum == 1) {
                return 1;
            }
            else {
                return -1;
            }
        }
        // If key is less then minimum then return minimum
        // because it will be successor of the key
        else if (helper.minimum != -1
                 && key < helper.minimum) {
            return helper.minimum;
        }
        else {
 
            // Find successor inside the cluster of the key
            // First find the maximum in the cluster
            int max_incluster = VEB_maximum(
                helper.clusters.get(helper.high(key)));
            int offset = 0;
            int succ_cluster = 0;
 
            // If there is any key( maximum!=-1 ) present in
            // the cluster then find the successor inside of
            // the cluster
            if (max_incluster != -1
                && helper.low(key) < max_incluster) {
                offset = VEB_successor(
                    helper.clusters.get(helper.high(key)),
                    helper.low(key));
                return helper.generate_index(
                    helper.high(key), offset);
            }
            else {
                succ_cluster = VEB_successor(
                    helper.summary, helper.high(key));
                if (succ_cluster == -1) {
                    return -1;
                }
                // Find minimum in successor cluster which
                // will be the successor of the key
                else {
                    offset = VEB_minimum(
                        helper.clusters.get(succ_cluster));
                    return helper.generate_index(
                        succ_cluster, offset);
                }
            }
        }
    }
 
    // Function to find the predecessor of the given key
    public static int VEB_predecessor(Van_Emde_Boas helper,
                                      int key)
    {
        if (helper.universe_size == 2) {
            if (key == 1 && helper.minimum == 0) {
                return 0;
            }
            else {
                return -1;
            }
        }
        // If the key is greater than maximum of the tree
        // then
        // return key as it will be the predecessor of the
        // key
        else if (helper.maximum != -1
                 && key > helper.maximum) {
            return helper.maximum;
        }
        else {
            // Find predecessor in the cluster of the key
            // First find minimum in the key to check
            // whether any key is present in the cluster
            int min_incluster = VEB_minimum(
                helper.clusters.get(helper.high(key)));
            int offset = 0;
            int pred_cluster = 0;
 
            // If any key is present in the cluster then
            // find predecessor in the cluster
            if (min_incluster != -1
                && helper.low(key) > min_incluster) {
 
                offset = VEB_predecessor(
                    helper.clusters.get(helper.high(key)),
                    helper.low(key));
                return helper.generate_index(
                    helper.high(key), offset);
            }
            else {
                // returns the index of predecessor cluster
                // with any key present
                pred_cluster = VEB_predecessor(
                    helper.summary, helper.high(key));
                // If no predecessor cluster then...
                if (pred_cluster == -1) {
                    if (helper.minimum != -1
                        && key > helper.minimum) {
                        return helper.minimum;
                    }
                    else {
                        return -1;
                    }
                } // Otherwise find maximum in the
                  // predecessor cluster
                else {
                    offset = VEB_maximum(
                        helper.clusters.get(pred_cluster));
                    return helper.generate_index(
                        pred_cluster, offset);
                }
            }
        }
    }
 
    // Driver code
    public static void main(String[] args)
    {
        Van_Emde_Boas veb = new Van_Emde_Boas(8);
 
        insert(veb, 2);
        insert(veb, 3);
        insert(veb, 4);
        insert(veb, 6);
 
        System.out.println(VEB_successor(veb, 2));
        System.out.println(VEB_predecessor(veb, 6));
        System.out.println(VEB_successor(veb, 4));
    }
}




import math
 
class Van_Emde_Boas:
    # Constructor
    def __init__(self, size):
        self.universe_size = size
        self.minimum = None
        self.maximum = None
        if size <= 2:
            self.summary = None
            self.clusters = [None] * 0
        else:
            no_clusters = math.ceil(math.sqrt(size))
            self.summary = Van_Emde_Boas(no_clusters)
            self.clusters = [Van_Emde_Boas(
                math.ceil(math.sqrt(size))) for i in range(no_clusters)]
 
    #  Function to return cluster numbers
    # in which key is present
    def high(self, x):
        div = math.ceil(math.sqrt(self.universe_size))
        return x // div
 
    def low(self, x):
        mod = math.ceil(math.sqrt(self.universe_size))
        return x % mod
 
    # Function to return the index from
   # cluster number and position
    def generate_index(self, x, y):
        ru = math.ceil(math.sqrt(self.universe_size))
        return (x or 0) * ru + (y or 0)
 
# Function to return the minimum value
#  from the tree if it exists
def VEB_minimum(helper):
    return helper.minimum
 
# Function to return the maximum value
# from the tree if it exists
def VEB_maximum(helper):
    return helper.maximum
 
 
#  Function to insert a key in the tree
def insert(helper, key):
     #  If no key is present in the tree
        # then set both minimum and maximum
        # to the key (Read the previous article
        # for more understanding about it)
    if helper.minimum is None:
        helper.minimum = key
        helper.maximum = key
    else:
        if key < helper.minimum:
        # If the key is less than the current minimum
        # then swap it with the current minimum
        # because this minimum is actually
        # minimum of one of the internal cluster
        # so as we go deeper into the Van Emde Boas
        # we need to take that minimum to its real position
        # This concept is similar to "Lazy Propagation"
            helper.minimum, key = key, helper.minimum
        if helper.universe_size > 2:
            if VEB_minimum(helper.clusters[helper.high(key)]) is None:
                insert(helper.summary, helper.high(key))
                # Sets the minimum and maximum of cluster to the key
                #  as no other keys are present we will stop at this level
                #  we are not going deeper into the structure like
                #  Lazy Propagation
                
                helper.clusters[helper.high(key)].minimum = helper.low(key)
                helper.clusters[helper.high(key)].maximum = helper.low(key)
            else:
                # If there are other elements in the tree then recursively
                # go deeper into the structure to set attributes accordingly
                insert(helper.clusters[helper.high(key)], helper.low(key))
        if key > helper.maximum:
            helper.maximum = key
 
# Function to find the successor of the given key
def VEB_successor(helper, x):
     
        # Base case: If key is 0 and its successor
    # is present then return 1 else return null
    if helper.universe_size == 2:
        if x == 0 and helper.maximum == 1:
            return 1
        else:
            return None
             
    # If key is less then minimum then return minimum
    # because it will be successor of the key
    elif helper.minimum is not None and x < helper.minimum:
        return helper.minimum
    else:
         
        # Find successor inside the cluster of the key
        # First find the maximum in the cluster
        max_in_cluster = VEB_maximum(helper.clusters[helper.high(x)])
         
        # If there is any key( maximum!=-1 ) present in the cluster then find
        # the successor inside of the cluster
        if max_in_cluster is not None and helper.low(x) < max_in_cluster:
            offset = VEB_successor(helper.clusters[helper.high(x)], helper.low(x))
            return helper.generate_index(helper.high(x), offset)
         
        # Otherwise look for the next cluster with at least one key present
        else:
            succ_cluster = VEB_successor(helper.summary, helper.high(x))
             
            # If there is no cluster with any key present
            # in summary then return null
            if succ_cluster is None:
                return None
                 
            # Find minimum in successor cluster which will
            # be the successor of the key
            else:
                offset = VEB_minimum(helper.clusters[succ_cluster])
                return helper.generate_index(succ_cluster, offset)
 
# Function to find the predecessor of the given key
def VEB_predecessor(helper, x):
     
    # Base case: If the key is 1 and it's predecessor
    # is present then return 0 else return null
    if helper.universe_size == 2:
        if x == 1 and helper.minimum == 0:
            return 0
        else:
            return None
     
   
    # If the key is greater than maximum of the tree then
    # return key as it will be the predecessor of the key
    elif helper.maximum is not None and x > helper.maximum:
        return helper.maximum
    else:
         
        # Find predecessor in the cluster of the key
        # First find minimum in the key to check whether any key
        # is present in the cluster
        min_in_cluster = VEB_minimum(helper.clusters[helper.high(x)])
         
        # If any key is present in the cluster then find predecessor in
        # the cluster
        if min_in_cluster is not None and helper.low(x) > min_in_cluster:
            offset = VEB_predecessor(helper.clusters[helper.high(x)], helper.low(x))
            return helper.generate_index(helper.high(x), offset)
         
        # Otherwise look for predecessor in the summary which
        # returns the index of predecessor cluster with any key present
        else:
            pred_cluster = VEB_predecessor(helper.summary, helper.high(x))
             
            # If no predecessor cluster then...
            if pred_cluster is None:
                 
                    # Special case which is due to lazy propagation
                if helper.minimum is not None and x > helper.minimum:
                    return helper.minimum
                else:
                    return None
          # Otherwise find maximum in the predecessor cluster
            else:
                offset = VEB_maximum(helper.clusters[pred_cluster])
                return helper.generate_index(pred_cluster, offset)
 
# Driver code
veb = Van_Emde_Boas(6)
# Inserting keys
insert(veb, 2)
insert(veb, 3)
insert(veb, 4)
insert(veb, 6)
 
print(VEB_successor(veb, 2))
print(VEB_predecessor(veb,6))
print(VEB_successor(veb, 4))




using System;
using System.Collections.Generic;
 
public class Van_Emde_Boas {
 
    public int universe_size;
    public int minimum;
    public int maximum;
    public Van_Emde_Boas summary;
    public List<Van_Emde_Boas> clusters;
 
    public Van_Emde_Boas(int size)
    {
        universe_size = size;
        minimum = -1;
        maximum = -1;
 
        // Base case
        if (size <= 2) {
            summary = null;
            clusters = new List<Van_Emde_Boas>(0);
        }
        else {
            int no_clusters
                = (int)Math.Ceiling(Math.Sqrt(size));
            summary = new Van_Emde_Boas(no_clusters);
 
            clusters
                = new List<Van_Emde_Boas>(no_clusters);
 
            for (int i = 0; i < no_clusters; i++) {
                clusters.Add(new Van_Emde_Boas(
                    (int)Math.Ceiling(Math.Sqrt(size))));
            }
        }
    }
 
    // Function to return cluster numbers
    // in which key is present
    public int high(int x)
    {
        int div = (int)Math.Ceiling(Math.Sqrt(universe_size));
        return x / div;
    }
    // Function to return position of x in cluster
    public int low(int x)
    {
        int mod = (int)Math.Ceiling(Math.Sqrt(universe_size));
        return x % mod;
    }
 
    // Function to return position of x in cluster
    public int generate_index(int x, int y)
    {
        int ru = (int)Math.Ceiling(Math.Sqrt(universe_size));
        return x * ru + y;
    }
}
 
public class Main_Program {
  
  
    // Function to return the minimum value
    // from the tree if it exists
    public static int VEB_minimum(Van_Emde_Boas helper)
    {
        return (helper.minimum == -1 ? -1 : helper.minimum);
    }
 
    // Function to return the maximum value
    // from the tree if it exists
    public static int VEB_maximum(Van_Emde_Boas helper)
    {
        return (helper.maximum == -1 ? -1 : helper.maximum);
    }
 
 
    // Function to insert a key in the tree
    static void insert(Van_Emde_Boas helper, int key)
    {
         
    // If no key is present in the tree
        // then set both minimum and maximum
        // to the key (Read the previous article
        // for more understanding about it)
        if (helper.minimum == -1) {
            helper.minimum = key;
            helper.maximum = key;
        }
        else {
 
    // If the key is less than the current minimum
            // then swap it with the current minimum
            // because this minimum is actually
            // minimum of one of the internal cluster
            if (key < helper.minimum) {
                int temp = helper.minimum;
                helper.minimum = key;
                key = temp;
            }
 
            // Not base case then...
            if (helper.universe_size > 2) {
 
 
                // If no key is present in the cluster then
                // insert key into both cluster and summary
                if (VEB_minimum(helper.clusters[helper.high(key)])
                    == -1) {
                    insert(helper.summary,
                        helper.high(key));
 
                     // Sets the minimum and maximum of
                    // cluster to the key as no other keys
                    // are present we will stop at this
                    // level
                    helper.clusters[helper.high(key)]
                        .minimum
                        = helper.low(key);
                    helper.clusters[helper.high(key)]
                        .maximum
                        = helper.low(key);
                }
                else {
 
                    // If there are other elements in the
                    // tree then recursively go deeper into
                    // the structure to set attributes
                    // accordingly 
                    insert(helper.clusters[
                            helper.high(key)],
                        helper.low(key));
                }
            }
   // Sets the key as maximum it is greater than
            // current maximum
            if (key > helper.maximum) {
                helper.maximum = key;
            }
        }
    }
 
// Function to find the successor of the given key
public static int VEB_successor(Van_Emde_Boas helper, int key)
{
    if (helper.universe_size == 2)
    {
        if (key == 0 && helper.maximum == 1)
        {
            return 1;
        }
        else
        {
            return -1;
        }
    }
        // If key is less then minimum then return minimum
        // because it will be successor of the key
    else if (helper.minimum != -1 && key < helper.minimum)
    {
        return helper.minimum;
    }
    else
    {
         
            // Find successor inside the cluster of the key
            // First find the maximum in the cluster
        int max_incluster = VEB_maximum(helper.clusters[helper.high(key)]);
        int offset = 0;
        int succ_cluster = 0;
 
 
            // If there is any key( maximum!=-1 ) present in
            // the cluster then find the successor inside of
            // the cluster
        if (max_incluster != -1 && helper.low(key) < max_incluster)
        {
            offset = VEB_successor(helper.clusters[helper.high(key)], helper.low(key));
            return helper.generate_index(helper.high(key), offset);
        }
        else
        {
            succ_cluster = VEB_successor(helper.summary, helper.high(key));
            if (succ_cluster == -1)
            {
                return -1;
            }
            else
            {
                // Find minimum in successor cluster which
                // will be the successor of the key
                offset = VEB_minimum(helper.clusters[succ_cluster]);
                return helper.generate_index(succ_cluster, offset);
            }
        }
    }
}
 
    // Function to find the predecessor of the given key
 public static int VEB_predecessor(Van_Emde_Boas helper, int key) {
        if (helper.universe_size == 2) {
            if (key == 1 && helper.minimum == 0) {
                return 0;
            }
            else {
                return -1;
            }
        }
                // If the key is greater than maximum of the tree
        // then
        // return key as it will be the predecessor of the
        // key
        else if (helper.maximum != -1 && key > helper.maximum) {
            return helper.maximum;
        }
        else {
                // Find predecessor in the cluster of the key
            // First find minimum in the key to check
            // whether any key is present in the cluster
            int min_incluster = VEB_minimum(helper.clusters[helper.high(key)]);
            int offset = 0;
            int pred_cluster = 0;
 
        // If any key is present in the cluster then
            // find predecessor in the cluster
            if (min_incluster != -1 && helper.low(key) > min_incluster) {
                offset = VEB_predecessor(
                    helper.clusters[helper.high(key)],
                    helper.low(key));
                return helper.generate_index(helper.high(key), offset);
            }
            else {
                        // returns the index of predecessor cluster
                // with any key present
                pred_cluster = VEB_predecessor(
                    helper.summary, helper.high(key));
 
                if (pred_cluster == -1) {
                    if (helper.minimum != -1 && key > helper.minimum) {
                        return helper.minimum;
                    }
                    else {
                        return -1;
                    }
                }
                // Otherwise find maximum in the
                // predecessor cluster
                else {
                    offset = VEB_maximum(helper.clusters[pred_cluster]);
                    return helper.generate_index(pred_cluster, offset);
                }
            }
        }
    }
     
        // Driver code
     public static void Main() {
        Van_Emde_Boas veb = new Van_Emde_Boas(8);
        insert(veb, 2);
        insert(veb, 3);
        insert(veb, 4);
        insert(veb, 6);
         Console.WriteLine(VEB_successor(veb, 2));
        Console.WriteLine(VEB_predecessor(veb, 6));
          Console.WriteLine(VEB_successor(veb, 4));
    }
}




class VanEmdeBoas {
    constructor(size) {
        this.universe_size = size;
        this.minimum = -1;
        this.maximum = -1;
        this.summary = null;
        this.clusters = [];
 
        if (size <= 2) {
            this.summary = null;
            this.clusters = new Array(0).fill(null);
        } else {
            const no_clusters = Math.ceil(Math.sqrt(size));
            this.summary = new VanEmdeBoas(no_clusters);
            this.clusters = new Array(no_clusters).fill(null);
 
            for (let i = 0; i < no_clusters; i++) {
                this.clusters[i] = new VanEmdeBoas(Math.ceil(Math.sqrt(size)));
            }
        }
    }
 
    high(x) {
        const div = Math.ceil(Math.sqrt(this.universe_size));
        return Math.floor(x / div);
    }
 
    low(x) {
        const mod = Math.ceil(Math.sqrt(this.universe_size));
        return x % mod;
    }
 
    generate_index(x, y) {
        const ru = Math.ceil(Math.sqrt(this.universe_size));
        return x * ru + y;
    }
}
 
function VEB_minimum(helper) {
    return helper.minimum === -1 ? -1 : helper.minimum;
}
 
function VEB_maximum(helper) {
    return helper.maximum === -1 ? -1 : helper.maximum;
}
 
function insert(helper, key) {
    if (helper.minimum === -1) {
        helper.minimum = key;
        helper.maximum = key;
    } else {
        if (key < helper.minimum) {
            [helper.minimum, key] = [key, helper.minimum];
        }
        if (helper.universe_size > 2) {
            if (VEB_minimum(helper.clusters[helper.high(key)]) === -1) {
                insert(helper.summary, helper.high(key));
                helper.clusters[helper.high(key)].minimum = helper.low(key);
                helper.clusters[helper.high(key)].maximum = helper.low(key);
            } else {
                insert(helper.clusters[helper.high(key)], helper.low(key));
            }
        }
        if (key > helper.maximum) {
            helper.maximum = key;
        }
    }
}
 
function isMember(helper, key) {
    if (helper.universe_size < key) {
        return false;
    }
    if (helper.minimum === key || helper.maximum === key) {
        return true;
    }
    if (helper.universe_size === 2) {
        return false;
    }
    return isMember(helper.clusters[helper.high(key)], helper.low(key));
}
 
function VEB_successor(helper, key) {
    if (helper.universe_size === 2) {
        if (key === 0 && helper.maximum === 1) {
            return 1;
        } else {
            return -1;
        }
    }
    if (helper.minimum !== -1 && key < helper.minimum) {
        return helper.minimum;
    }
    const max_incluster = VEB_maximum(helper.clusters[helper.high(key)]);
    let offset = 0;
    let succ_cluster = 0;
    if (max_incluster !== -1 && helper.low(key) < max_incluster) {
        offset = VEB_successor(helper.clusters[helper.high(key)], helper.low(key));
        return helper.generate_index(helper.high(key), offset);
    }
    succ_cluster = VEB_successor(helper.summary, helper.high(key));
    if (succ_cluster === -1) {
        return -1;
    }
    offset = VEB_minimum(helper.clusters[succ_cluster]);
    return helper.generate_index(succ_cluster, offset);
}
 
function VEB_predecessor(helper, key) {
    if (helper.universe_size === 2) {
        if (key === 1 && helper.minimum === 0) {
            return 0;
        } else {
            return -1;
        }
    }
    if (helper.maximum !== -1 && key > helper.maximum) {
        return helper.maximum;
    }
    const min_incluster = VEB_minimum(helper.clusters[helper.high(key)]);
    let offset = 0;
    let pred_cluster = 0;
    if (min_incluster !== -1 && helper.low(key) > min_incluster) {
        offset = VEB_predecessor(helper.clusters[helper.high(key)], helper.low(key));
        return helper.generate_index(helper.high(key), offset);
    }
    pred_cluster = VEB_predecessor(helper.summary, helper.high(key));
    if (pred_cluster === -1) {
        if (helper.minimum !== -1 && key > helper.minimum) {
            return helper.minimum;
        } else {
            return -1;
        }
    }
    offset = VEB_maximum(helper.clusters[pred_cluster]);
    return helper.generate_index(pred_cluster, offset);
}
 
const veb = new VanEmdeBoas(8);
insert(veb, 2);
insert(veb, 3);
insert(veb, 4);
insert(veb, 6);
console.log(VEB_successor(veb, 2));
console.log(VEB_predecessor(veb, 6));
console.log(VEB_successor(veb, 4));

Output
3
4
6

Time Complexity: O(log2(u)*log2(log2(u))) per query
Auxiliary Space: O(N). 


Article Tags :