Open In App

Proto Van Emde Boas Trees | Set 4 | Deletion

Improve
Improve
Improve
Like Article
Like
Save Article
Save
Share
Report issue
Report

Please check previous sets of Proto Van Emde Boas Tree article first. It is highly recommended.
Procedure for delete: 
 

  1. Base Case: If we reach at Proto VEB with size 2 then we will check for whether the key is present or not if yes then we assign the pointer to nullptr which will set false to it presence.
  2. Recursion: 
    • We recursively call delete function over the cluster of the keys i.e. high(key) and its position low(key).
    • After we delete the key from the cluster (after we reach to the base case) we check whether there are any other keys are present in the cluster. If there is any key present then we can not set the summary to nullptr otherwise we will set the summary to nullptr by calling delete over summary. 
       


Lets understand 1 delete on Proto-VEB of size 4: 
First it will recursively call delete(cluster[0], 1). 
So now the base case is satisfied so it will go at position 1 in the cluster[0] Proto-VEB and will set it to nullptr if it is present.
Now we will check if any more keys are present in cluster[0] (see the for loop in delete), 0 is present so delete(summary, 0) call is not going to execute and summary will remain same.
See the image below to understand it:
Follow the instructions written near the boxes from top to bottom.
 

Deletion in Proto-VEB


Below is the implementation:
 

CPP

// C++ implementation of the approach
#include <bits/stdc++.h>
using namespace std;
 
class Proto_Van_Emde_Boas {
public:
    // Total number of keys
    int universe_size;
 
    // Summary
    Proto_Van_Emde_Boas* summary;
 
    // Clusters array of Proto-VEB pointers
    vector<Proto_Van_Emde_Boas*> clusters;
 
    int root(int u)
    {
        return int(sqrt(u));
    }
 
    // Function to return cluster numbers
    // in which key is present
    int high(int x)
    {
        return x / root(universe_size);
    }
 
    // Function to return position of x in cluster
    int low(int x)
    {
        return x % root(universe_size);
    }
 
    // Function to return the index from
    // cluster number and position
    int generate_index(int cluster, int position)
    {
        return cluster * root(universe_size) + position;
    }
 
    // Constructor
    Proto_Van_Emde_Boas(int size)
    {
        universe_size = size;
 
        // Base case
        if (size <= 2) {
 
            // Set summary to nullptr as there is no
            // more summary for size 2
            summary = nullptr;
 
            // Vector of two pointers
            // nullptr in starting
            clusters = vector<Proto_Van_Emde_Boas*>(size, nullptr);
        }
        else {
 
            // Assigning Proto-VEB(sqrt(u)) to summary
            summary = new Proto_Van_Emde_Boas(root(size));
 
            // Creating array of Proto-VEB Tree pointers of size sqrt(u)
            // first all nullptrs are going to assign
            clusters = vector<Proto_Van_Emde_Boas*>(root(size), nullptr);
 
            // Assigning Proto-VEB(sqrt(u)) to all its clusters
            for (int i = 0; i < root(size); i++) {
                clusters[i] = new Proto_Van_Emde_Boas(root(size));
            }
        }
    }
};
 
// Function that returns true if the
// key is present in the tree
bool isMember(Proto_Van_Emde_Boas* helper, int key)
{
 
    // If key is greater then universe_size then
    // returns false
    if (key >= helper->universe_size)
        return false;
 
    // If we reach at base case
    // the just return whether
    // pointer is nullptr then false
    // else return true
    if (helper->universe_size == 2) {
        return helper->clusters[key];
    }
    else {
 
        // Recursively go deep into the
        // level of Proto-VEB tree using its
        // cluster index and its position
        return isMember(helper->clusters[helper->high(key)],
                        helper->low(key));
    }
}
 
// Function to insert a key in the tree
void insert(Proto_Van_Emde_Boas*& helper, int key)
{
    // If we reach at base case
    // then assign Proto-VEB(1) in place
    // of nullptr
    if (helper->universe_size == 2) {
        helper->clusters[key] = new Proto_Van_Emde_Boas(1);
    }
    else {
 
        // Recursively using index of cluster and its
        // position in cluster
        insert(helper->clusters[helper->high(key)],
               helper->low(key));
 
        // Also do the same recursion in summary VEB
        insert(helper->summary, helper->high(key));
    }
}
 
// Function to delete a key from the tree
void pveb_delete(Proto_Van_Emde_Boas*& helper, int key)
{
 
    // Base case: If the key is present
    // then make it nullptr
    if (helper->universe_size == 2) {
        if (helper->clusters[key]) {
            delete helper->clusters[key];
            helper->clusters[key] = nullptr;
        }
    }
    else {
 
        // Recursive delete to reach at the base case
        pveb_delete(helper->clusters[helper->high(key)], helper->low(key));
 
        bool isanyinCluster = false;
 
        // Iterate over the cluster of keys to check whether
        // any other key is present within that cluster
        // If yes then we should not update summary to 0
        // else update summary to 0
        for (int i = helper->high(key) * helper->root(helper->universe_size);
             i < (helper->high(key) + 1) * helper->root(helper->universe_size);
             i++) {
 
            // If member is present then break the loop
            if (isMember(helper->clusters[helper->high(key)], i)) {
                isanyinCluster = true;
                break;
            }
        }
 
        // If no member is present then
        // update summary to zero
        if (isanyinCluster == false) {
            pveb_delete(helper->summary, helper->high(key));
        }
    }
}
 
// Driver code
int main()
{
    Proto_Van_Emde_Boas* hello = new Proto_Van_Emde_Boas(4);
 
    cout << isMember(hello, 2);
 
    insert(hello, 2);
 
    insert(hello, 3);
 
    cout << isMember(hello, 2);
 
    pveb_delete(hello, 2);
 
    cout << isMember(hello, 2);
}

                    

Java

// Java implementation of the approach
import java.util.*;
 
class Proto_Van_Emde_Boas {
 
  // Total number of keys
  int universe_size;
  Proto_Van_Emde_Boas summary;
 
  // Clusters array of Proto-VEB pointers
  ArrayList<Proto_Van_Emde_Boas> clusters;
 
  Proto_Van_Emde_Boas(int size) {
    universe_size = size;
 
    // Base case
    if (size <= 2) {
 
      // Set summary to nullptr as there is no
      // more summary for size 2
      summary = null;
      clusters = new ArrayList<Proto_Van_Emde_Boas>(size);
      for (int i = 0; i < size; i++) {
        clusters.add(null);
      }
    } else {
      summary = new Proto_Van_Emde_Boas(root(size));
 
      // Creating array of Proto-VEB Tree pointers of size sqrt(u)
      // first all nullptrs are going to assign
      clusters = new ArrayList<Proto_Van_Emde_Boas>(root(size));
 
      // Assigning Proto-VEB(sqrt(u)) to all its clusters
      for (int i = 0; i < root(size); i++) {
        clusters.add(new Proto_Van_Emde_Boas(root(size)));
      }
    }
  }
 
  int root(int u) {
    return (int) Math.sqrt(u);
  }
  // Function to return cluster numbers
  // in which key is present
  int high(int x) {
    return x / root(universe_size);
  }
 
  int low(int x) {
    return x % root(universe_size);
  }
  // return the index from cluster number and position
  int generate_index(int cluster, int position) {
    return cluster * root(universe_size) + position;
  }
 
}
 
class Solution {
 
  //returns true if the key is present in the tree
  public static boolean isMember(Proto_Van_Emde_Boas helper, int key) {
 
    // If key is greater then universe_size then
    // returns false
    if (key >= helper.universe_size) {
      return false;
    }
 
    // pointer is nullptr then false
    // else return true
    if (helper.universe_size == 2) {
      return helper.clusters.get(key) != null;
    } else {
 
      // Recursively go deep into the
      // level of Proto-VEB tree using its
      // cluster index and its position
      return isMember(helper.clusters.get(helper.high(key)), helper.low(key));
    }
  }
 
  // Function to insert a key in the tree
  public static void insert(Proto_Van_Emde_Boas helper, int key) {
 
    if (helper.universe_size == 2) {
      helper.clusters.set(key, new Proto_Van_Emde_Boas(1));
    } else {
 
      // Recursively using index of cluster and its
      // position in cluster
      insert(helper.clusters.get(helper.high(key)), helper.low(key));
      insert(helper.summary, helper.high(key));
    }
  }
 
  // Function to delete a key from the tree
  public static void pveb_delete(Proto_Van_Emde_Boas helper, int key) {
 
    // If the key is present then make it nullptr
    if (helper.universe_size == 2) {
      if (helper.clusters.get(key) != null) {
        helper.clusters.set(key, null);
      }
    } else {
      pveb_delete(helper.clusters.get(helper.high(key)), helper.low(key));
 
      boolean isanyinCluster = false;
 
      // Iterate over the cluster of keys to check whether
      // any other key is present within that cluster
      // If yes then we should not update summary to 0
      // else update summary to 0
      for (int i = helper.high(key) * helper.root(helper.universe_size);
           i < (helper.high(key) + 1) * helper.root(helper.universe_size);
           i++) {
        if (isMember(helper.clusters.get(helper.high(key)), i)) {
          isanyinCluster = true;
          break;
        }
      }
      // If no member is present then
      // update summary to zero
      if (!isanyinCluster) {
        pveb_delete(helper.summary, helper.high(key));
      }
    }
  }
 
 
  // Driver code
  public static void main(String[] args) {
 
    Proto_Van_Emde_Boas hello = new Proto_Van_Emde_Boas(4);
 
    // checking it is member or not by isMember
    System.out.println(isMember(hello, 2));
 
    // inserting
    insert(hello, 2);
    insert(hello, 3);
 
    // again checking it is member or not by isMember
    System.out.println(isMember(hello, 2));
 
    // deleting
    pveb_delete(hello, 2);
 
    // checking it is member or not by isMember
    System.out.println(isMember(hello, 2));
  }
}

                    

Python3

# Python implementation
import math
 
class ProtoVanEmdeBoas:
  def __init__(self, size):
    self.universeSize = size
 
   
    # Set summary to null as there is no
    # more summary for size 2
    if size <= 2:
      self.summary = None
      self.clusters = [None] * size
    else:
      self.summary = ProtoVanEmdeBoas(self.Root(size))
 
      self.clusters = [ProtoVanEmdeBoas(self.Root(size)) for i in range(self.Root(size))]
 
  def Root(self, u):
    return int(math.sqrt(u))
 
  def High(self, x):
    return int(x / self.Root(self.universeSize))
 
  def Low(self, x):
    return x % self.Root(self.universeSize)
 
  def GenerateIndex(self, cluster, position):
    return cluster * self.Root(self.universeSize) + position
 
 
    #  Function that returns true if the key is present in
    #  the tree
def IsMember(helper, key):
     
    #  If key is greater than or equal to universeSize
    #  then return false
  if key >= helper.universeSize:
    return False
 
 
    #  If we reach at base case
    #  the just return whether
    #  pointer is nullptr then false
    #  else return true
  if helper.universeSize == 2:
    return helper.clusters[key] != None
  else:
         
    #  Recursively go deep into the
    #  level of Proto-VEB tree using its
    #  cluster index and its position
    return IsMember(helper.clusters[helper.High(key)], helper.Low(key))
 
# Function to insert a key in the tree
def Insert(helper, key):
     
    # If we reach at base case
    # then assign Proto-VEB(1) in place
    # of nullptr
  if helper.universeSize == 2:
    helper.clusters[key] = ProtoVanEmdeBoas(1)
  else:
       
        # Recursively using index of cluster and its
        # position in cluster
    Insert(helper.clusters[helper.High(key)], helper.Low(key))
     
    # Also do the same recursion in summary VEB
    Insert(helper.summary, helper.High(key))
 
#  Function to delete a key from the tree
def PvebDelete(helper, key):
     
    # Base case: If the key is present
    # then make it nullptr
  if helper.universeSize == 2:
    if helper.clusters[key] != None:
      helper.clusters[key] = None
  else:
    # Recursive delete to reach at the base case
    PvebDelete(helper.clusters[helper.High(key)], helper.Low(key))
 
    isAnyInCluster = False
 
        # Iterate over the cluster of keys to check whether
        # any other key is present within that cluster
        # If yes then we should not update summary to 0
        # else update summary to 0
         
    for i in range(helper.High(key) * helper.Root(helper.universeSize), (helper.High(key) + 1) * helper.Root(helper.universeSize)):
         
      # If member is present then break the loop
      if IsMember(helper.clusters[helper.High(key)], i):
        isAnyInCluster = True
        break
     
    # If no member is present then
    # update summary to zero
    if not isAnyInCluster:
      PvebDelete(helper.summary, helper.High(key))
 
# Driver Code
hello = ProtoVanEmdeBoas(4)
 
# Checking the membership
print(IsMember(hello, 2))
 
# Inserting
Insert(hello, 2)
Insert(hello, 3)
 
# Checking the membership
print(IsMember(hello, 2))
 
# deleting
PvebDelete(hello, 2)
print(IsMember(hello, 2))

                    

Javascript

class ProtoVanEmdeBoas {
  constructor(size) {
    this.universeSize = size;
 
    if (size <= 2) {
            // Set summary to null as there is no
            // more summary for size 2
      this.summary = null;
      this.clusters = new Array(size).fill(null);
    } else {
      this.summary = new ProtoVanEmdeBoas(this.Root(size));
       
          // Creating array of Proto-VEB Tree pointers of size sqrt(u)
        // first all nulls are going to assign
      this.clusters = new Array(this.Root(size)).fill(null).map(() => new ProtoVanEmdeBoas(this.Root(size)));
    }
  }
 
  Root(u) {
    return Math.floor(Math.sqrt(u));
  }
 
    // Function to return cluster numbers
    // in which key is present
  High(x) {
    return Math.floor(x / this.Root(this.universeSize));
  }
  
 // Function to return position of x in cluster
  Low(x) {
    return x % this.Root(this.universeSize);
  }
 
// return the index from cluster number and position
  GenerateIndex(cluster, position) {
    return cluster * this.Root(this.universeSize) + position;
  }
}
 
    // Function that returns true if the key is present in
    // the tree
function IsMember(helper, key) {
     
    // If key is greater than or equal to universeSize
        // then return false
  if (key >= helper.universeSize) {
    return false;
  }
 
    // If we reach at base case
    // the just return whether
    // pointer is nullptr then false
    // else return true
  if (helper.universeSize === 2) {
    return helper.clusters[key] !== null;
  } else {
       
          // Recursively go deep into the
        // level of Proto-VEB tree using its
        // cluster index and its position
    return IsMember(helper.clusters[helper.High(key)], helper.Low(key));
  }
}
 
// Function to insert a key in the tree
function Insert(helper, key) {
     
    // If we reach at base case
    // then assign Proto-VEB(1) in place
    // of nullptr
  if (helper.universeSize === 2) {
    helper.clusters[key] = new ProtoVanEmdeBoas(1);
  }
  else
  {
          // Recursively using index of cluster and its
        // position in cluster
    Insert(helper.clusters[helper.High(key)], helper.Low(key));
     
    // Also do the same recursion in summary VEB
    Insert(helper.summary, helper.High(key));
  }
}
 
// Function to delete a key from the tree
function PvebDelete(helper, key) {
     
    // Base case: If the key is present
    // then make it nullptr
  if (helper.universeSize === 2) {
    if (helper.clusters[key] !== null) {
      helper.clusters[key] = null;
    }
  } else {
       
      // Recursive delete to reach at the base case
    PvebDelete(helper.clusters[helper.High(key)], helper.Low(key));
 
    let isAnyInCluster = false;
 
        // Iterate over the cluster of keys to check whether
        // any other key is present within that cluster
        // If yes then we should not update summary to 0
        // else update summary to 0
    for (let i = helper.High(key) * helper.Root(helper.universeSize); i < (helper.High(key) + 1) * helper.Root(helper.universeSize); i++) {
         
        // If member is present then break the loop
      if (IsMember(helper.clusters[helper.High(key)], i)) {
        isAnyInCluster = true;
        break;
      }
    }
 
    // If no member is present then
        // update summary to zero
    if (!isAnyInCluster) {
      PvebDelete(helper.summary, helper.High(key));
    }
  }
}
 
// Driver code
const hello = new ProtoVanEmdeBoas(4);
 
console.log(IsMember(hello, 2));
Insert(hello, 2);
Insert(hello, 3);
console.log(IsMember(hello, 2));
PvebDelete(hello, 2);
console.log(IsMember(hello, 2));

                    

C#

using System;
using System.Collections.Generic;
 
public class  ProtoVanEmdeBoas
{
    // Total number of keys
   public int universeSize;
   public  ProtoVanEmdeBoas summary;
 
    // Clusters array of Proto-VEB pointers
    public List< ProtoVanEmdeBoas> clusters;
 
    public  ProtoVanEmdeBoas(int size)
    {
        universeSize = size;
 
        // Base case
        if (size <= 2)
        {
            // Set summary to null as there is no
            // more summary for size 2
            summary = null;
            clusters = new List<ProtoVanEmdeBoas>(size);
            for (int i = 0; i < size; i++)
            {
                clusters.Add(null);
            }
        }
        else
        {
            summary = new  ProtoVanEmdeBoas(Root(size));
 
            // Creating array of Proto-VEB Tree pointers of size sqrt(u)
            // first all nulls are going to assign
            clusters = new List< ProtoVanEmdeBoas>(Root(size));
 
            // Assigning Proto-VEB(sqrt(u)) to all its clusters
            for (int i = 0; i < Root(size); i++)
            {
                clusters.Add(new ProtoVanEmdeBoas(Root(size)));
            }
        }
    }
 
   public int Root(int u)
    {
        return (int)Math.Sqrt(u);
    }
 
    // Function to return cluster numbers
    // in which key is present
    public int High(int x)
    {
        return x / Root(universeSize);
    }
 
   public int Low(int x)
    {
        return x % Root(universeSize);
    }
 
    // return the index from cluster number and position
    int GenerateIndex(int cluster, int position)
    {
        return cluster * Root(universeSize) + position;
    }
}
 
public class Solution
{
        // Function that returns true if the key is present in
    // the tree
    static bool IsMember(ProtoVanEmdeBoas helper, int key)
    {
 
        // If key is greater than or equal to universeSize
        // then return false
        if (key >= helper.universeSize)
        {
            return false;
        }
 
        if (helper.universeSize == 2)
        {
            return helper.clusters[key] != null;
        }
        else
        {
            return IsMember(
                helper.clusters[helper.High(key)],
                helper.Low(key));
        }
    }
   // Function to insert a key in the tree
    static void Insert(ProtoVanEmdeBoas helper, int key)
    {
        if (helper.universeSize == 2)
        {
            helper.clusters[key] = new ProtoVanEmdeBoas(1);
        }
        else
        {
            Insert(helper.clusters[helper.High(key)],
                helper.Low(key));
            // Also do the same recursion in summary VEB
            Insert(helper.summary, helper.High(key));
        }
    }
 
    // Function to delete a key from the tree
    public static void PvebDelete( ProtoVanEmdeBoas helper, int key)
    {
        // If the key is present then make it null
        if (helper.universeSize == 2)
        {
            if (helper.clusters[key] != null)
            {
                helper.clusters[key] = null;
            }
        }
        else
        {
            PvebDelete(helper.clusters[helper.High(key)], helper.Low(key));
 
            bool isanyinCluster = false;
 
            // Iterate over the cluster of keys to check whether
            // any other key is present within that cluster
            // If yes then we should not update summary to 0
            // else update summary to 0
            for (int i = helper.High(key) * helper.Root(helper.universeSize);
                i < (helper.High(key) + 1) * helper.Root(helper.universeSize);
                i++)
            {
                if (IsMember(helper.clusters[helper.High(key)], i))
                {
                    isanyinCluster = true;
                    break;
                }
            }
 
            // If no member is present then update summary to zero
            if (!isanyinCluster)
            {
                PvebDelete(helper.summary, helper.High(key));
            }
        }
    }
 static void Main()
    {
        ProtoVanEmdeBoas hello = new ProtoVanEmdeBoas(4);
 
        // checking is member or not by calling isMember func.
        Console.WriteLine(IsMember(hello, 2));
 
        // inserting
        Insert(hello, 2);
        Insert(hello, 3);
  Console.WriteLine(IsMember(hello, 2));
   
    // deleting
    PvebDelete(hello, 2);
     
    // checking is member or not by calling isMember func.
     Console.WriteLine(IsMember(hello, 2));
}}

                    

Recurrence Relation for Delete:
 

T(u) = T(u) = 2T(\sqrt{u})) + O(log2(\sqrt{u}))


Time Complexity : O(log2(u)*log2(log2(u)))
 



Last Updated : 10 Apr, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads