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

}
### 作用分析 `local_Rb_tree_decrement` 函数的作用是实现红黑树中节点的“前驱”查找功能。在红黑树结构中,节点的前驱是指在中序遍历顺序中紧接在当前节点之前的节点。该函数通过一系列逻辑判断和操作,找到当前节点的前驱节点,从而支持红黑树的迭代器递减操作。 --- ### 实现分析 函数的实现逻辑可以分为以下几个部分: #### 1. **特殊处理 Header 节点** 如果当前节点 `__x` 是 Header 节点(即红黑树的根节点的父节点,且颜色为红色),则直接返回其右子节点 `__x->_M_right`。这是因为在红黑树的实现中,Header 节点的右子节点通常指向树的最大节点。 ```cpp if (__x->_M_color == _S_red && __x->_M_parent->_M_parent == __x) { __x = __x->_M_right; } ``` #### 2. **左子树不为空时** 如果当前节点 `__x` 的左子节点不为空,则需要在左子树中找到最大的节点(即最右下角的节点),这个节点就是当前节点的前驱节点。通过循环遍历左子树的右子节点,直到找到最后一个右子节点为最大节点。 ```cpp else if (__x->_M_left != 0) { _Rb_tree_node_base* __y = __x->_M_left; while (__y->_M_right != 0) { __y = __y->_M_right; } __x = __y; } ``` #### 3. **左子树为空时** 如果当前节点 `__x` 的左子树为空,则需要通过向上回溯的方式,找到其前驱节点。具体实现是沿着父节点向上遍历,直到找到一个节点 `__y`,该节点是其父节点的右子节点,此时 `__y` 的父节点就是前驱节点。 ```cpp else { _Rb_tree_node_base* __y = __x->_M_parent; while (__x == __y->_M_left) { __x = __y; __y = __y->_M_parent; } __x = __y; } ``` --- ### 代码总结 通过上述实现逻辑,`local_Rb_tree_decrement` 函数能够准确地找到红黑树中当前节点的前驱节点。该函数在红黑树的迭代器操作中扮演重要角色,确保了红黑树的高效性和完整性。 ```cpp static _Rb_tree_node_base* local_Rb_tree_decrement(_Rb_tree_node_base* __x) throw() { if (__x->_M_color == _S_red && __x->_M_parent->_M_parent == __x) { __x = __x->_M_right; } else if (__x->_M_left != 0) { _Rb_tree_node_base* __y = __x->_M_left; while (__y->_M_right != 0) { __y = __y->_M_right; } __x = __y; } else { _Rb_tree_node_base* __y = __x->_M_parent; while (__x == __y->_M_left) { __x = __y; __y = __y->_M_parent; } __x = __y; } return __x; } ``` --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值