Data Structure
Networking
RDBMS
Operating System
Java
MS Excel
iOS
HTML
CSS
Android
Python
C Programming
C++
C#
MongoDB
MySQL
Javascript
PHP
- Selected Reading
- UPSC IAS Exams Notes
- Developer's Best Practices
- Questions and Answers
- Effective Resume Writing
- HR Interview Questions
- Computer Glossary
- Who is Who
C++ Program to Implement Randomized Binary Search Tree
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.
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
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.