rb_tree(红黑树)

#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);

}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值