382 lines
9.4 KiB
C
382 lines
9.4 KiB
C
#include <stddef.h> //for NULL
|
|
#include "../inc/rbtree.h"
|
|
|
|
#define rbtree_black 0
|
|
#define rbtree_red 1
|
|
|
|
void rbtree_init(rbtree_t *tree){
|
|
if(tree == NULL)
|
|
return;
|
|
|
|
tree->sentinel.left = &tree->sentinel;
|
|
tree->sentinel.right = &tree->sentinel;
|
|
tree->sentinel.parent = &tree->sentinel;
|
|
tree->sentinel.color = rbtree_black;
|
|
|
|
tree->root = &tree->sentinel;
|
|
|
|
return;
|
|
}
|
|
|
|
void rbtree_destory(rbtree_t *tree){
|
|
if(tree == NULL)
|
|
return;
|
|
|
|
tree->root = &tree->sentinel;
|
|
}
|
|
|
|
static void rbtree_left_rotate(rbtree_t *tree,rbtree_node_t* x){
|
|
if(x == &tree->sentinel){
|
|
return;
|
|
}
|
|
|
|
rbtree_node_t*y = x->right;
|
|
if(y == &tree->sentinel){
|
|
return;
|
|
}
|
|
|
|
x->right = y->left;
|
|
if(y->left != &tree->sentinel){
|
|
y->left->parent = x;
|
|
}
|
|
|
|
y->parent = x->parent;
|
|
if(x == tree->root){
|
|
tree->root = y;
|
|
}else if(x == x->parent->left){
|
|
x->parent->left = y;
|
|
}else{
|
|
x->parent->right = y;
|
|
}
|
|
|
|
x->parent = y;
|
|
y->left = x;
|
|
|
|
return;
|
|
}
|
|
|
|
static void rbtree_right_rotate(rbtree_t *tree,rbtree_node_t* x){
|
|
if(x == &tree->sentinel){
|
|
return;
|
|
}
|
|
|
|
rbtree_node_t*y = x->left;
|
|
if(y == &tree->sentinel){
|
|
return;
|
|
}
|
|
|
|
x->left = y->right;
|
|
if(y->right != &tree->sentinel){
|
|
y->right->parent = x;
|
|
}
|
|
|
|
y->parent = x->parent;
|
|
if(x == tree->root){
|
|
tree->root = y;
|
|
}else if(x == x->parent->left){
|
|
x->parent->left = y;
|
|
}else{
|
|
x->parent->right = y;
|
|
}
|
|
|
|
x->parent = y;
|
|
y->right = x;
|
|
|
|
return;
|
|
}
|
|
|
|
void rbtree_insert(rbtree_t *tree,rbtree_node_t* node){
|
|
if(tree == NULL || node == NULL || node == &tree->sentinel)
|
|
return;
|
|
|
|
rbtree_node_t *x,*x_tmp;
|
|
x = tree->root;
|
|
x_tmp = &tree->sentinel;
|
|
while(x != &tree->sentinel){
|
|
if(node->key<x->key){
|
|
x_tmp = x;
|
|
x = x->left;
|
|
}else{
|
|
x_tmp = x;
|
|
x = x->right;
|
|
}
|
|
}
|
|
|
|
node->parent = x_tmp;
|
|
node->left = &tree->sentinel;
|
|
node->right = &tree->sentinel;
|
|
node->color = rbtree_red;
|
|
|
|
if(tree->root == &tree->sentinel){
|
|
tree->root = node;
|
|
}else if(node->key < x_tmp->key){
|
|
x_tmp->left = node;
|
|
}else{
|
|
x_tmp->right = node;
|
|
}
|
|
|
|
while(node->parent->color == rbtree_red){
|
|
|
|
if(node->parent == node->parent->parent->left){
|
|
x = node->parent->parent->right;
|
|
if(x->color == rbtree_red){
|
|
node->parent->color = rbtree_black;
|
|
x->color = rbtree_black;
|
|
node->parent->parent->color = rbtree_red;
|
|
node = node->parent->parent;
|
|
}else{
|
|
if(node == node->parent->right){
|
|
node = node->parent;
|
|
rbtree_left_rotate(tree,node);
|
|
}
|
|
|
|
node->parent->color = rbtree_black;
|
|
node->parent->parent->color = rbtree_red;
|
|
rbtree_right_rotate(tree,node->parent->parent);
|
|
}
|
|
}else{
|
|
x = node->parent->parent->left;
|
|
if(x->color == rbtree_red){
|
|
node->parent->color = rbtree_black;
|
|
x->color = rbtree_black;
|
|
node->parent->parent->color = rbtree_red;
|
|
node = node->parent->parent;
|
|
}else{
|
|
if(node == node->parent->left){
|
|
node = node->parent;
|
|
rbtree_right_rotate(tree,node);
|
|
}
|
|
|
|
node->parent->color = rbtree_black;
|
|
node->parent->parent->color = rbtree_red;
|
|
rbtree_left_rotate(tree,node->parent->parent);
|
|
}
|
|
}
|
|
|
|
}
|
|
tree->root->color = rbtree_black;
|
|
return;
|
|
}
|
|
|
|
static rbtree_node_t* rbtree_min_node(rbtree_t *tree,rbtree_node_t* node){
|
|
while(node->left != &tree->sentinel){
|
|
node = node->left;
|
|
}
|
|
return node;
|
|
}
|
|
|
|
void rbtree_delete(rbtree_t *tree,rbtree_node_t* node){
|
|
if(tree == NULL || node == NULL || node == &tree->sentinel){
|
|
return;
|
|
}
|
|
|
|
if(node->left == NULL || node->right == NULL || node->parent == NULL){
|
|
return;
|
|
}
|
|
|
|
rbtree_node_t *temp,*subst,*w;
|
|
unsigned char color;
|
|
|
|
if(node->left == &tree->sentinel){
|
|
subst = node;
|
|
temp = node->right;
|
|
}else if(node->right == &tree->sentinel){
|
|
subst = node;
|
|
temp = node->left;
|
|
}else{
|
|
subst = rbtree_min_node(tree,node->right);
|
|
temp = subst->right;
|
|
}
|
|
|
|
|
|
if(subst == tree->root){
|
|
tree->root = temp;
|
|
temp->color = rbtree_black;
|
|
temp->parent = &tree->sentinel;
|
|
|
|
node->left = NULL;
|
|
node->right = NULL;
|
|
node->parent = NULL;
|
|
|
|
tree->sentinel.parent = &tree->sentinel;
|
|
return;
|
|
}
|
|
|
|
color = subst->color;
|
|
|
|
if(subst == subst->parent->left){
|
|
subst->parent->left = temp;
|
|
}else{
|
|
subst->parent->right = temp;
|
|
}
|
|
|
|
if(subst == node){
|
|
temp->parent = subst->parent;
|
|
}else{
|
|
if(subst->parent == node){
|
|
temp->parent = subst;
|
|
}else{
|
|
temp->parent = subst->parent;
|
|
}
|
|
subst->left = node->left;
|
|
subst->right = node->right;
|
|
subst->parent = node->parent;
|
|
subst->color = node->color;
|
|
|
|
if(node == tree->root){
|
|
tree->root = subst;
|
|
}else{
|
|
if(node == node->parent->left){
|
|
node->parent->left = subst;
|
|
}else{
|
|
node->parent->right = subst;
|
|
}
|
|
}
|
|
|
|
if(subst->left != &tree->sentinel){
|
|
subst->left->parent = subst;
|
|
}
|
|
|
|
if(subst->right != &tree->sentinel){
|
|
subst->right->parent = subst;
|
|
}
|
|
}
|
|
|
|
node->left = NULL;
|
|
node->right = NULL;
|
|
node->parent = NULL;
|
|
|
|
if(color == rbtree_red){
|
|
tree->sentinel.parent = &tree->sentinel;
|
|
return;
|
|
}
|
|
|
|
while(temp != tree->root && temp->color == rbtree_black){
|
|
if(temp == temp->parent->left){
|
|
w = temp->parent->right;
|
|
if(w->color == rbtree_red){
|
|
w->color = rbtree_black;
|
|
temp->parent->color = rbtree_red;
|
|
rbtree_left_rotate(tree,temp->parent);
|
|
w = temp->parent->right;
|
|
}
|
|
|
|
if(w->left->color == rbtree_black && w->right->color == rbtree_black){
|
|
w->color = rbtree_red;
|
|
temp = temp->parent;
|
|
}else{
|
|
if(w->left->color == rbtree_red){
|
|
w->color = rbtree_red;
|
|
w->left->color = rbtree_black;
|
|
rbtree_right_rotate(tree,w);
|
|
w = temp->parent->right;
|
|
}
|
|
|
|
w->color = temp->parent->color;
|
|
temp->parent->color = rbtree_black;
|
|
w->right->color = rbtree_black;
|
|
rbtree_left_rotate(tree,temp->parent);
|
|
temp = tree->root;
|
|
}
|
|
}else{
|
|
w = temp->parent->left;
|
|
if(w->color == rbtree_red){
|
|
w->color = rbtree_black;
|
|
temp->parent->color = rbtree_red;
|
|
rbtree_right_rotate(tree,temp->parent);
|
|
w = temp->parent->left;
|
|
}
|
|
|
|
if(w->left->color == rbtree_black && w->right->color == rbtree_black){
|
|
w->color = rbtree_red;
|
|
temp = temp->parent;
|
|
}else{
|
|
if(w->right->color == rbtree_red){
|
|
w->color = rbtree_red;
|
|
w->right->color = rbtree_black;
|
|
rbtree_left_rotate(tree,w);
|
|
w = temp->parent->left;
|
|
}
|
|
|
|
w->color = temp->parent->color;
|
|
temp->parent->color = rbtree_black;
|
|
w->left->color = rbtree_black;
|
|
rbtree_right_rotate(tree,temp->parent);
|
|
temp = tree->root;
|
|
}
|
|
}
|
|
}
|
|
|
|
temp->color = rbtree_black;
|
|
|
|
tree->sentinel.parent = &tree->sentinel;
|
|
|
|
return;
|
|
}
|
|
|
|
rbtree_node_t* rbtree_search(rbtree_t *tree,uint64_t key){
|
|
if(tree == NULL)
|
|
return NULL;
|
|
|
|
rbtree_node_t *node = tree->root;
|
|
while(node != &tree->sentinel){
|
|
if(key == node->key){
|
|
break;
|
|
}else if(key < node->key){
|
|
node = node->left;
|
|
}else{
|
|
node = node->right;
|
|
}
|
|
}
|
|
|
|
if(node == &tree->sentinel){
|
|
node = NULL;
|
|
}
|
|
|
|
return node;
|
|
}
|
|
|
|
rbtree_node_t* rbtree_min(rbtree_t *tree,rbtree_node_t* node){
|
|
if(tree == NULL || node == NULL || node==&tree->sentinel){
|
|
return NULL;
|
|
}
|
|
|
|
if(node->left == NULL || node->right == NULL || node->parent == NULL){
|
|
return NULL;
|
|
}
|
|
|
|
while(node->left != &tree->sentinel){
|
|
node = node->left;
|
|
}
|
|
if(node == &tree->sentinel){
|
|
node = NULL;
|
|
}
|
|
return node;
|
|
}
|
|
|
|
rbtree_node_t* rbtree_next(rbtree_t *tree,rbtree_node_t* node){
|
|
if(node == NULL || node == NULL || node == &tree->sentinel){
|
|
return NULL;
|
|
}
|
|
|
|
if(node->left == NULL || node->right == NULL || node->parent == NULL){
|
|
return NULL;
|
|
}
|
|
|
|
if(node->right != &tree->sentinel){
|
|
return rbtree_min(tree,node->right);
|
|
}
|
|
|
|
|
|
for(;;){
|
|
if(node == tree->root){
|
|
return NULL;
|
|
//return tree->sentinel;
|
|
}
|
|
|
|
if(node == node->parent->left){
|
|
return node->parent;
|
|
}
|
|
node = node->parent;
|
|
}
|
|
} |