Implement Randomized Binary Search Tree in C++



A Randomized Binary Search Tree (RBST) is a variation of a Binary Search Tree (BST) that contains randomization to maintain balance and improve efficiency. One common implementation of an RBST is a Treap, which combines BST properties with heap properties.

RBST

Why We Use Random Binary Tree

Random binary trees are used for analyzing the average-case complexity of data structure based on the binary trees.

Features of RBST

Following are the features of the randomized binary tree:

  • BST Properties: The left subtree contains smaller value, right subtree contains larger value.
  • Randomization: Each node assigned a random property, ensuring a balanced structure with high probability.
  • Efficient Operation: Expected time complexity for search, insert, and delete id O(log n).
  • Self-Balancing: Unlike AVL or Red-black tree, RBSTs use randomization instead of strict balancing rules.

How We Implement RBST

We can implement the randomized binary search tree using the Treap: Treap is a balanced binary search tree in which every node contains two values key and priority. Where the key follows standard BST order, and priority is the randomly assigned value that follows Max-Heap Property.

Basic Operation on Treap

Like another self-balancing binary search tree, Treap uses rotation to maintain Max-heap during insertion and deletion.

T1, T2, and T3 are subtrees of the tree rooted at y on the left side or x on the right side.

Keys in both of the above trees follow the following order 
keys(T1) < key(x) < keys(T2) < key(y) < keys(T3)
So BST property is not violated anywhere. 

Implementation of Randomized Binary Searched Tree

Following are the implementation of the searched, Insert, and Delete in Treap:

Search

The search operation is the same as BST. Priority is not considered for search:

TreapNode* search(TreapNode* root, int key)
{
   if (root == NULL || root->key == key)
     return root;
   
   // Key is greater than key of root
   if (root->key < key)
     return search(root->right, key);
 
   // Key is smaller than key of root
   return search(root->left, key);
}

Insert

Here, we perform a standard BST insert to create a new node with a key equal to 'X' and a value equal to a random value.

TreapNode* insert(TreapNode* root, int key)
{
   if (!root)
       return newNode(key);

   if (key <= root->key)
   {
      // Insert in left subtree
      root->left = insert(root->left, key);
      
      // Fix Heap property if it is violated
      if (root->left->priority > root->priority)
         root = rightRotate(root);
   }
   else
   {
      // Insert in right subtree
      root->right = insert(root->right, key);
      
      // Fix Heap property if it is violated
      if (root->right->priority > root->priority)
         root = leftRotate(root);
   }
   return root;
}

Delete

The below code implements the delete operation.

TreapNode * deleteNode(TreapNode * root, int key) {
   if (root == NULL) return root;

   // IF KEYS IS NOT AT ROOT
   if (key < root -> key)
      root -> left = deleteNode(root -> left, key);
   else if (key > root -> key)
      root -> right = deleteNode(root -> right, key);

   // IF KEY IS AT ROOT
   // If left is NULL
   else if (root -> left == NULL) {
      TreapNode * temp = root -> right;
      delete(root);
      // Make right child as root
      root = temp;
   }

   // If Right is NULL
   else if (root -> right == NULL) {
      TreapNode * temp = root -> left;
      delete(root);
      // Make left child as root
      root = temp;
   }

   // If key is at root and both left and right are not NULL
   else if (root -> left -> priority < root -> right -> priority) {
      root = leftRotate(root);
      root -> left = deleteNode(root -> left, key);
   } else {
      root = rightRotate(root);
      root -> right = deleteNode(root -> right, key);
   }
   return root;
}

Implementation of Randomized Binary Tree

In the following example, we implement RBST including operations like search, insert, and delete with the help of Treap in C++:

#include <bits/stdc++.h>
using namespace std;

struct TreapNode {
   int key, priority;
   TreapNode * left, * right;
};

TreapNode * rightRotate(TreapNode * y) {
   TreapNode * x = y -> left, * T2 = x -> right;

   // Perform rotation
   x -> right = y;
   y -> left = T2;

   // Return new root
   return x;
}

TreapNode * leftRotate(TreapNode * x) {
   TreapNode * y = x -> right, * T2 = y -> left;

   // Perform rotation
   y -> left = x;
   x -> right = T2;

   // Return new root
   return y;
}

TreapNode * newNode(int key) {
   TreapNode * temp = new TreapNode;
   temp -> key = key;
   temp -> priority = rand() % 100;
   temp -> left = temp -> right = NULL;
   return temp;
}

TreapNode * search(TreapNode * root, int key) {
   // Base Cases: root is null or key is present at root
   if (root == NULL || root -> key == key)
      return root;

   // Key is greater than root's key
   if (root -> key < key)
      return search(root -> right, key);

   // Key is smaller than root's key
   return search(root -> left, key);
}

TreapNode * insert(TreapNode * root, int key) {
   // If root is NULL, create a new node and return it
   if (!root)
      return newNode(key);

   // If key is smaller than root
   if (key <= root -> key) {
      // Insert in left subtree
      root -> left = insert(root -> left, key);

      // Fix Heap property if it is violated
      if (root -> left -> priority > root -> priority)
         root = rightRotate(root);
   } else // If key is greater
   {
      // Insert in right subtree
      root -> right = insert(root -> right, key);

      // Fix Heap property if it is violated
      if (root -> right -> priority > root -> priority)
         root = leftRotate(root);
   }
   return root;
}
TreapNode * deleteNode(TreapNode * root, int key) {
   if (root == NULL)
      return root;

   if (key < root -> key)
      root -> left = deleteNode(root -> left, key);
   else if (key > root -> key)
      root -> right = deleteNode(root -> right, key);

   // IF KEY IS AT ROOT

   // If left is NULL
   else if (root -> left == NULL) {
      TreapNode * temp = root -> right;
      delete(root);
      root = temp; // Make right child as root
   }

   // If Right is NULL
   else if (root -> right == NULL) {
      TreapNode * temp = root -> left;
      delete(root);
      root = temp; // Make left child as root
   }

   // If key is at root and both left and right are not NULL
   else if (root -> left -> priority < root -> right -> priority) {
      root = leftRotate(root);
      root -> left = deleteNode(root -> left, key);
   } else {
      root = rightRotate(root);
      root -> right = deleteNode(root -> right, key);
   }

   return root;
}

void inorder(TreapNode * root) {
   if (root) {
      inorder(root -> left);
      cout << "key: " << root -> key << " | priority: " <<
         root -> priority;
      if (root -> left)
         cout << " | left child: " << root -> left -> key;
      if (root -> right)
         cout << " | right child: " << root -> right -> key;
      cout << endl;
      inorder(root -> right);
   }
}

int main() {
   srand(time(NULL));

   struct TreapNode * root = NULL;
   root = insert(root, 40);
   root = insert(root, 30);
   root = insert(root, 60);
   root = insert(root, 20);
   root = insert(root, 35);

   cout << "Inorder traversal of the given tree \n";
   inorder(root);

   cout << "\nDelete 20\n";
   root = deleteNode(root, 20);
   cout << "Inorder traversal of the modified tree \n";
   inorder(root);

   cout << "\nDelete 30\n";
   root = deleteNode(root, 30);
   cout << "Inorder traversal of the modified tree \n";
   inorder(root);

   TreapNode * res = search(root, 50);
   (res == NULL) ? cout << "\n50 Not Found ": cout << "\n50 found";

   return 0;
}

Following is the output of the above code:

Inorder traversal of the given tree 
key: 20 | priority: 29
key: 30 | priority: 98 | left child: 20
key: 35 | priority: 99 | left child: 30 | right child: 40
key: 40 | priority: 58 | right child: 60
key: 60 | priority: 39

Delete 20
Inorder traversal of the modified tree 
key: 30 | priority: 98
key: 35 | priority: 99 | left child: 30 | right child: 40
key: 40 | priority: 58 | right child: 60
key: 60 | priority: 39

Delete 30
Inorder traversal of the modified tree 
key: 35 | priority: 99 | right child: 40
key: 40 | priority: 58 | right child: 60
key: 60 | priority: 39

50 Not Found 
Updated on: 2025-05-29T15:45:27+05:30

669 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements