#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <assert.h>
enum RB_COLOR {BLACK = 0, RED = 1};
//------------------------------------------------------------------
int nodecount=0, nodecount2=0;
//------------------------------------------------------------------
//rbtreenode struct
struct rbtreenode_item {
enum RB_COLOR color;
int value;
void *data;
struct rbtreenode_item *left;
struct rbtreenode_item *right;
struct rbtreenode_item *parent;
};
typedef struct rbtreenode_item rbtreenode_t;
//rbtree
struct rbtree_item {
rbtreenode_t *root;
rbtreenode_t *nil;
};
typedef struct rbtree_item rbtree_t;
//-------------------------------------------------------------------
// rbtree functions
void rbtree_init(rbtree_t *rbtree);
void left_rotate(rbtree_t *rbtree, rbtreenode_t *xnode);
void right_rotate(rbtree_t *rbtree, rbtreenode_t *xnode);
void rbtree_insert(rbtree_t *rbtree, int value);
void rb_insert_fixup(rbtree_t *rbtree, rbtreenode_t *znode);
void rb_delete(rbtree_t *rbtree, rbtreenode_t *znode);
void rb_delete_fixup(rbtree_t *rbtree, rbtreenode_t *znode);
void rb_inorder(rbtreenode_t *rbtnode, rbtreenode_t *nil);
rbtreenode_t *rb_search_node(rbtree_t *rbtree, int value);
//===========================================================
// rb_search_node
// return a rbtreenode_t pointer base on the value
//===========================================================
rbtreenode_t *rb_search_node(rbtree_t *rbtree, int value) {
rbtreenode_t *xnode=NULL;
xnode = rbtree->root;
while(xnode != rbtree->nil) {
if(value > xnode->value)
xnode = xnode->right;
else if(value < xnode->value)
xnode = xnode->left;
else if(value == xnode->value)
return xnode;
}
xnode = NULL;
return xnode;
}
//===========================================================
// init a rbtree
//===========================================================
void rbtree_init(rbtree_t *rbtree) {
//make a nil node
rbtree->nil = (rbtreenode_t *)malloc(sizeof(rbtreenode_t));
rbtree->nil->value = 0;
rbtree->nil->color = BLACK;
rbtree->nil->data = NULL;
rbtree->nil->left = NULL;
rbtree->nil->right = NULL;
rbtree->nil->parent = NULL;
rbtree->root = rbtree->nil;
}
//=============================================================
// left_rotate
// make sure xnode->right != NULL
//=============================================================
void left_rotate(rbtree_t *rbtree, rbtreenode_t *xnode) {
rbtreenode_t *ynode;
//ynode is xnode's right child
ynode = xnode->right;
xnode->right = ynode->left;
if(ynode->left != rbtree->nil)
ynode->left->parent = xnode;
if(xnode != rbtree->nil)
ynode->parent = xnode->parent; //need fixup , xnode->parent may == NULL
if(xnode->parent == rbtree->nil) // root's parent is nil
rbtree->root = ynode; // so make ynode is root
else {
if(xnode->parent->left == xnode)
xnode->parent->left = ynode;
else
xnode->parent->right = ynode;
}
ynode->left = xnode;
if(xnode != rbtree->nil)
xnode->parent = ynode;
}
//==========================================================
// right_rotate
// make sure xnode->left != NULL
//==========================================================
void right_rotate(rbtree_t *rbtree, rbtreenode_t *xnode) {
rbtreenode_t *ynode;
//ynode is xnode's left child
ynode = xnode->left;
xnode->left = ynode->right;
if(ynode->right != rbtree->nil)
ynode->right->parent = xnode;
if(xnode != rbtree->nil)
ynode->parent = xnode->parent;
if(xnode->parent == rbtree->nil)
rbtree->root = ynode;
else {
if(xnode->parent->left == xnode)
xnode->parent->left = ynode;
else
xnode->parent->right = ynode;
}
ynode->right = xnode;
if(xnode != rbtree->nil)
xnode->parent = ynode;
}
//============================================================
// rbtree_insert
//============================================================
void rbtree_insert(rbtree_t *rbtree, int value) {
rbtreenode_t *xnode, *ynode, *znode;
xnode = rbtree->root;
ynode = rbtree->nil;
// znode is the new node to be inserted
znode = (rbtreenode_t *)malloc(sizeof(rbtreenode_t));
assert(znode);
znode->color = RED;
znode->data = NULL;
znode->value = value;
znode->parent = NULL;
znode->left = NULL;
znode->right = NULL;
while(xnode != rbtree->nil) {
ynode = xnode;
if(znode->value < xnode->value)
xnode = xnode->left;
else if(znode->value > xnode->value)
xnode = xnode->right;
else if(znode->value == xnode->value) { //value dup
free(znode);
return;
}
}
znode->parent = ynode;
if(ynode != rbtree->nil) {
if(znode->value > ynode->value)
ynode->right = znode;
else if(znode->value < ynode->value)
ynode->left = znode;
} else {
rbtree->root = znode; //znode is root
}
znode->left = rbtree->nil;
znode->right = rbtree->nil;
nodecount2++;
printf("<value: %d inserted>/n", znode->value);
rb_insert_fixup(rbtree, znode);
}
//================================================================
// rb_insert_fixup
// znode is the new child
//================================================================
void rb_insert_fixup(rbtree_t *rbtree, rbtreenode_t *znode) {
rbtreenode_t *ynode;
while((znode->parent != NULL) && (znode->parent->color == RED)) { //terminate when znode's parent is BLACK
// if znode->parent->color == RED, znode->parent->parent != NULL
if(znode->parent == znode->parent->parent->left) { //znode's parent is at left
ynode = znode->parent->parent->right; //ynode is znode's uncle
if((ynode != NULL) && (ynode->color == RED)) { //znode's parent and ynode is RED
znode->parent->color = BLACK; //change znode's parent to BLACK
ynode->color = BLACK; //change znode's uncle to BLACK
znode->parent->parent->color = RED; //change znode's grand father to RED
znode = znode->parent->parent; //znode is changed to its grand father
} else {
if(znode == znode->parent->right){ //ynode is BLACK and znode is right child
znode = znode->parent;
left_rotate(rbtree, znode);
}
/*
if(znode->parent == NULL) {
right_rotate(rbtree, znode);
continue;
}
*/
znode->parent->color = BLACK; //ynode is BLACK and znode is left child
znode->parent->parent->color = RED;
right_rotate(rbtree, znode->parent->parent);
}
} else { //znode's parent is at right
ynode = znode->parent->parent->left; //ynode is znode's uncle
if((ynode != NULL) && (ynode->color == RED)) {
znode->parent->color = BLACK;
ynode->color = BLACK;
znode->parent->parent->color = RED;
znode = znode->parent->parent;
} else {
if(znode == znode->parent->left) {
//error when znode is root, so znode parent is NULL
znode = znode->parent;
right_rotate(rbtree, znode);
}
/*
if(znode->parent == NULL) {
left_rotate(rbtree, znode);
continue;
}
*/
znode->parent->color = BLACK;
znode->parent->parent->color = RED;
left_rotate(rbtree, znode->parent->parent);
}
}
} //end while
rbtree->root->color = BLACK;
rbtree->nil->color = BLACK;
}
//========================================================================
// rb_delete_fixup
// fixup the rbtree when free a blacknode
//========================================================================
void rb_delete_fixup(rbtree_t *rbtree, rbtreenode_t *xnode) {
rbtreenode_t *wnode;
while((xnode != rbtree->root) && (xnode->color == BLACK)) {
if(xnode == xnode->parent->left) {//xnode is left node
wnode = xnode->parent->right;
if(wnode->color == RED) {
wnode->color = BLACK;
xnode->parent->color = RED;
left_rotate(rbtree, xnode->parent);
wnode = xnode->parent->right;
}
//wnode is black
if(wnode->left->color == BLACK && wnode->right->color == BLACK) {
wnode->color = RED;
xnode = xnode->parent;
} else {
if(wnode->right->color == BLACK) {
wnode->left->color = BLACK;
wnode->color = RED;
right_rotate(rbtree, wnode);
wnode = xnode->parent->right;
}
wnode->color = wnode->parent->color;
xnode->parent->color = BLACK;
wnode->right->color = BLACK;
left_rotate(rbtree, xnode->parent);
xnode = rbtree->root;
}
} else { //xnode is right node
wnode = xnode->parent->left;
if(wnode->color == RED) {
wnode->color = BLACK;
xnode->parent->color =RED;
right_rotate(rbtree, xnode->parent);
wnode = xnode->parent->left;
}
if(wnode->left->color == BLACK && wnode->right->color == BLACK) {
wnode->color = RED;
xnode = xnode->parent;
} else {
if(wnode->left->color == BLACK) {
wnode->right->color = BLACK;
wnode->color = RED;
left_rotate(rbtree, wnode);
wnode = xnode->parent->left;
}
wnode->color = wnode->parent->color;
xnode->parent->color = BLACK;
wnode->left->color = BLACK;
right_rotate(rbtree, xnode->parent);
xnode = rbtree->root;
}
}
}
xnode->color = BLACK;
}
//=======================================================================
// rb_delete
// delete znode from rbtree
//=======================================================================
void rb_delete(rbtree_t *rbtree, rbtreenode_t *znode) {
rbtreenode_t *ynode, *xnode;
if(znode->left == rbtree->nil || znode->right == rbtree->nil)
ynode = znode;
else {
ynode = znode->right;
while(ynode->left != rbtree->nil) ynode = ynode->left;//successor
//ynode = tree_successor(znode);
}
//xnode may sentinel???
if(ynode->left != rbtree->nil)
xnode = ynode->left;
else
xnode = ynode->right;
// if(xnode != rbtree->nil)
xnode->parent = ynode->parent;
if(ynode->parent == rbtree->nil)
rbtree->root = xnode;
else {
if(ynode->parent->left == ynode)
ynode->parent->left = xnode;
else
ynode->parent->right = xnode;
}
if (ynode != znode)
znode->value = ynode->value;
if (ynode->color == BLACK)
rb_delete_fixup(rbtree, xnode);
free(ynode);
}
//=================================================================
// rb_inorder
//=================================================================
void rb_inorder(rbtreenode_t *rbtnode, rbtreenode_t *nil) {
if(rbtnode != nil) {
nodecount++;
rb_inorder(rbtnode->left, nil);
printf("< value: %d, color: %d, parent is: %d >/n", rbtnode->value, rbtnode->color, rbtnode->parent->value);
if(rbtnode->color == RED && rbtnode->parent->color == RED) {
printf("error RED duped<%d, %d>", rbtnode->value, rbtnode->parent->value);
exit(0);
}
rb_inorder(rbtnode->right, nil);
}
}
//==================================================================
// main
//==================================================================
int main() {
int n, value;
rbtreenode_t *searchnode;
rbtree_t rbtree, *prbtree;
prbtree = &rbtree;
rbtree_init(prbtree);
// env 1
rbtree_insert(prbtree, 9);
rbtree_insert(prbtree, 1);
rbtree_insert(prbtree, 2);
rbtree_insert(prbtree, 4);
rbtree_insert(prbtree, 8);
rbtree_insert(prbtree, 5);
rbtree_insert(prbtree, 6);
rbtree_insert(prbtree, 3);
rbtree_insert(prbtree, 7);
printf("<inorder the tree>/n");
rb_inorder(prbtree->root, prbtree->nil);
printf("tree node count: %d/n", nodecount);
printf("insert node count: %d/n", nodecount2);
searchnode = rb_search_node(prbtree, 5);
if(!searchnode) {
printf("Can't find the node user give!/n");
exit(0);
}
rb_delete(prbtree, searchnode);
/*
*******************************************************
//env 2
srand(time(NULL));
for(n = 0; n < 999999; n++) {
value = rand() + rand() + rand();
rbtree_insert(prbtree, value);
}
for(n = 0; n < 999999; n++) {
value = rand() + rand() + rand();
rbtree_insert(prbtree, value);
}
//rbtree_insert(prbtree, 253466);
*******************************************************
*/
printf("<after delete inorder the tree>/n");
rb_inorder(prbtree->root, prbtree->nil);
for(n = 0; n < 999; n++) {
value = rand();
rbtree_insert(prbtree, value);
}
searchnode = rb_search_node(prbtree, 6875);
if(!searchnode) {
printf("Can't find the node user give!/n");
exit(0);
}
rb_delete(prbtree, searchnode);
searchnode = rb_search_node(prbtree, 96507);
if(!searchnode) {
printf("Can't find the node user give!/n");
exit(0);
}
rb_delete(prbtree, searchnode);
rb_inorder(prbtree->root, prbtree->nil);
// printf("tree node count: %d/n", nodecount);
// printf("insert node count: %d/n", nodecount2);
}
rb_tree(红黑树)
最新推荐文章于 2018-11-28 16:25:34 发布