I'm trying to implement binary search tree operations MIN
and MAX
efficiently, in O(1)
time. I see if BST
is balanced, then these take O(lgn)
in the worst-case; otherwise, O(h)
, where h is the height of the root of the bst, worst-case runtime. But both of them isn't efficient considering that (max/min)heap provide O(1)
time to get min
and max
. I've tried to augment bst to get max and min in constant time, but I got doubts on it. The implementation is in C programming language:
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <math.h>
typedef struct node {
int key;
struct node* left, * right, * parent, * min, * max;
}augmented_bst;
augmented_bst* find_min(augmented_bst* node) {
if (!node)
return node;
return node->min;
}
augmented_bst* next_larger(augmented_bst* node) {
if (!node)
return node;
if (node->right)
return node->right->min;
while (node->parent && node->parent->right == node)
node = node->parent;
return node->parent;
}
augmented_bst* new_Node(int x) {
augmented_bst* node = (augmented_bst*)malloc(sizeof(augmented_bst));
assert(node != NULL);
node->key = x;
node->left = node->right = NULL;
node->min = node->max = node;
return node;
}
void insert(augmented_bst** root, int x) {
augmented_bst* node = new_Node(x);
if (!node)
return;
if (!*root)
*root = node;
else if ((*root)->key > node->key) {
if ((*root)->min->key > node->key)
(*root)->min = node;
if (!(*root)->left) {
(*root)->left = node;
node->parent = *root;
}
else {
insert(&(*root)->left, x);
}
}
else {
if ((*root)->max->key < node->key)
(*root)->max = node;
if (!(*root)->right) {
(*root)->right = node;
node->parent = *root;
}
else {
insert(&(*root)->right, x);
}
}
}
augmented_bst* search_tree(augmented_bst* root, int x) {
if (root == NULL || root->key == x)
return root;
if (root->key > x)
return search_tree(root->left, x);
return search_tree(root->right, x);
}
void TRANSPLANT(augmented_bst* root, augmented_bst* u, augmented_bst* v) {
if (u->parent == NULL)
root = v;
else if (u->parent->left == u)
u->parent->left = v;
else
u->parent->right = v;
if (v != NULL)
v->parent = u->parent;
}
void fixMin(augmented_bst** node) {
if (!*node)
return;
augmented_bst* current = *node;
while (current->parent && current->parent->left == current) {
current->parent->min = current->min;
current = current->parent;
}
}
void fixMax(augmented_bst** node) {
if (!*node)
return;
augmented_bst* current = node;
while (current->parent && current->parent->right == current) {
current->parent->max = current->max;
current = current->parent;
}
}
void DELETE(augmented_bst** root, int x) {
augmented_bst* node = search_tree(*root, x);
assert(node != NULL);
if (!node->right) {
TRANSPLANT(*root, node, node->left);
fixMin(&node);
}
else if (!node->left) {
TRANSPLANT(*root, node, node->right);
fixMax(&node);
}
else {
augmented_bst* temp = next_larger(node);
if (node->right != temp) {
TRANSPLANT(*root, temp, temp->right);
fixMin(&temp->right);
temp->right = node->right;
temp->right->parent = temp;
temp->max = node->right->max;
}
TRANSPLANT(*root, node, temp);
fixMax(&temp);
temp->left = node->left;
temp->left->parent = temp;
temp->min = temp->left->min;
}
}
NOTES: some procedures in the code is take from CLRS. I put whole implementation thinking someone might need it. My problem is with the DELETE
procedure, but you can suggest anything about other parts of the code. If you think this can be done in better way, please state it. I used fixMin
and fixMax
functions four times inside DELETE
procedure. Can we do it better? If yes, how? Is there a better (or different) way to implement DELETE
procedure? I appreciate your answers and am open to any suggestions about anything.