Recently, because of the support for CCache to join the red-black tree, find the code that has been implemented as a reference, this only to find that the original implementation is problematic, but also blame my test case writing is not good, just the insertion of the test, I have read this code and caused confusion of friends to apologize.
This time, all the code was rewritten, referenced the implementation algorithm of the red and black tree in the Linux kernel, and the test case was strengthened, hopefully this is the last revision of the red-black tree algorithm.
/*-----------------------------------------------------------
An implementation algorithm of Rb-tree insertion and deletion operation
Resources:
1) <<introduction to algorithm>>
2) http://lxr.linux.no/linux/lib/rbtree.c
Author: http://www.cppblog.com/converse/
You can freely spread, modify this code, reprint place Please indicate the original author
Several properties of red and black trees:
1 Each node is only red and black two colors
2) The root node is black
3 The Empty node is black (in the red and black tree, the parent of the root node and all leaf nodes lchild and rchild do not point to null, but point to a well-defined empty node).
4 If a node is red, then the color of its left and right two sub nodes is black
5 for each node, the black node on any path from this node to the leaf node
The same number of
-------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef int key_t;
typedef int data_t;
typedef enum COLOR_T
{
RED = 0,
Black = 1
}color_t;
typedef struct RB_NODE_T
{
struct rb_node_t *left, *right, *parent;
key_t key;
data_t data;
color_t color;
}rb_node_t;
/* Forward Declaration * *
rb_node_t* Rb_insert (key_t key, data_t data, rb_node_t* root);
rb_node_t* Rb_search (key_t key, rb_node_t* root);
rb_node_t* rb_erase (key_t key, rb_node_t* root);
int main ()
{
int I, count = 900000;
key_t key;
rb_node_t* root = null, *node = NULL;
Srand (Time (NULL));
for (i = 1; i < count; ++i)
{
Key = rand ()% count;
if ((Root = Rb_insert (key, I, Root))
{
printf ("[i =%d] Insert key%d success!\n", I, key);
}
Else
{
printf ("[i =%d] Insert key%d error!\n", I, key);
Exit (-1);
}
if (node = Rb_search (key, Root))
{
printf ("[i =%d] search key%d success!\n", I, key);
}
Else
{
printf ("[i =%d] search key%d error!\n", I, key);
Exit (-1);
}
if (!) ( I% 10))
{
if ((Root = Rb_erase (key, Root))
{
printf ("[i =%d] Erase key%d success\n", I, key);
}
Else
{
printf ("[i =%d] Erase key%d error\n", I, key);
}
}
}
return 0;
}
Static rb_node_t* Rb_new_node (key_t key, data_t data)
{
rb_node_t *node = (rb_node_t*) malloc (sizeof (struct rb_node_t));
if (!node)
{
printf ("malloc error!\n");
Exit (-1);
}
Node->key = key, node->data = data;
return node;
}
/*-----------------------------------------------------------
| Node Right
| /\ ==>/\
| A right node Y
| / \ / \
| b y a B
-----------------------------------------------------------*/
Static rb_node_t* Rb_rotate_left (rb_node_t* node, rb_node_t* root)
{
rb_node_t* right = node->right;
if ((Node->right = Right->left))
{
right->left->parent = node;
}
right->left = node;
if ((right->parent = node->parent))
{
if (node = = node->parent->right)
{
Node->parent->right = right;
}
Else
{
Node->parent->left = right;
}
}
Else
{
root = right;
}
Node->parent = right;
return root;
}
/*-----------------------------------------------------------
| Node left
| / \ / \
| Left Y ==> a node
| / \ / \
| A b b y
-----------------------------------------------------------*/
Static rb_node_t* Rb_rotate_right (rb_node_t* node, rb_node_t* root)
{
rb_node_t* left = node->left;
if ((Node->left = left->right))
{
left->right->parent = node;
}
left->right = node;
if ((left->parent = node->parent))
{
if (node = = node->parent->right)
{
Node->parent->right = left;
}
Else
{
Node->parent->left = left;
}
}
Else
{
root = left;
}
Node->parent = left;
return root;
}
Static rb_node_t* rb_insert_rebalance (rb_node_t *node, rb_node_t *root)
{
rb_node_t *parent, *gparent, *uncle, *tmp;
while (parent = node->parent) && Parent->color = = RED)
{
Gparent = parent->parent;
if (parent = = Gparent->left)
{
Uncle = gparent->right;
if (Uncle && uncle->color = = RED)
{
Uncle->color = black;
Parent->color = black;
Gparent->color = RED;
node = gparent;
}
Else
{
if (parent->right = node)
{
Root = Rb_rotate_left (parent, root);
TMP = parent;
parent = node;
node = tmp;
}
Parent->color = black;
Gparent->color = RED;
Root = Rb_rotate_right (gparent, Root);
}
}
Else
{
Uncle = gparent->left;
if (Uncle && uncle->color = = RED)
{
Uncle->color = black;
Parent->color = black;
Gparent->color = RED;
node = gparent;
}
Else
{
if (Parent->left = node)
{
Root = Rb_rotate_right (parent, root);
TMP = parent;
parent = node;
node = tmp;
}
Parent->color = black;
Gparent->color = RED;
Root = Rb_rotate_left (gparent, Root);
}
}
}
Root->color = black;
return root;
}
Static rb_node_t* rb_erase_rebalance (rb_node_t *node, rb_node_t *parent, rb_node_t *root)
{
rb_node_t *other, *o_left, *o_right;
while ((!node | | node->color = black) && node!= root)
{
if (Parent->left = node)
{
other = parent->right;
if (Other->color = = RED)
{
Other->color = black;
Parent->color = RED;
Root = Rb_rotate_left (parent, root);
other = parent->right;
}
if (!other->left | | other->left->color = black) &&
(!other->right | | other->right->color = black))
{
Other->color = RED;
node = parent;
Parent = node->parent;
}
Else
{
if (!other->right | | other->right->color = black)
{
if ((O_left = Other->left))
{
O_left->color = black;
}
Other->color = RED;
Root = Rb_rotate_right (other, root);
other = parent->right;
}
Other->color = parent->color;
Parent->color = black;
if (other->right)
{
Other->right->color = black;
}
Root = Rb_rotate_left (parent, root);
node = root;
Break
}
}
Else
{
other = parent->left;
if (Other->color = = RED)
{
Other->color = black;
Parent->color = RED;
Root = Rb_rotate_right (parent, root);
other = parent->left;
}
if (!other->left | | other->left->color = black) &&
(!other->right | | other->right->color = black))
{
Other->color = RED;
node = parent;
Parent = node->parent;
}
Else
{
if (!other->left | | other->left->color = black)
{
if ((O_right = other->right))
{
O_right->color = black;
}
Other->color = RED;
Root = Rb_rotate_left (other, root);
other = parent->left;
}
Other->color = parent->color;
Parent->color = black;
if (other->left)
{
Other->left->color = black;
}
Root = Rb_rotate_right (parent, root);
node = root;
Break
}
}
}
if (node)
{
Node->color = black;
}
return root;
}
Static rb_node_t* rb_search_auxiliary (key_t key, rb_node_t* root, rb_node_t** Save)
{
rb_node_t *node = root, *parent = NULL;
int ret;
while (node)
{
parent = node;
RET = node->key-key;
if (0 < ret)
{
node = node->left;
}
else if (0 > Ret)
{
node = node->right;
}
Else
{
return node;
}
}
if (save)
{
*save = parent;
}
return NULL;
}
rb_node_t* Rb_insert (key_t key, data_t data, rb_node_t* root)
{
rb_node_t *parent = NULL, *node;
parent = NULL;
if (node = Rb_search_auxiliary (key, Root, &parent))
{
return root;
}
node = Rb_new_node (key, data);
Node->parent = parent;
Node->left = Node->right = NULL;
Node->color = RED;
if (parent)
{
if (Parent->key > key)
{
parent->left = node;
}
Else
{
parent->right = node;
}
}
Else
{
root = node;
}
Return Rb_insert_rebalance (node, root);
}
rb_node_t* Rb_search (key_t key, rb_node_t* root)
{
Return Rb_search_auxiliary (key, Root, NULL);
}
rb_node_t* rb_erase (key_t key, rb_node_t *root)
{
rb_node_t *child, *parent, *old, *left, *node;
color_t color;
if (!) ( node = Rb_search_auxiliary (key, Root, NULL))
{
printf ("Key%d is not exist!\n");
return root;
}
old = node;
if (Node->left && node->right)
{
node = node->right;
while (left = node->left)!= NULL)
{
node = left;
}
Child = node->right;
Parent = node->parent;
color = node->color;
if (child)
{
Child->parent = parent;
}
if (parent)
{
if (Parent->left = node)
{
Parent->left = child;
}
Else
{
Parent->right = child;
}
}
Else
{
root = child;
}
if (node->parent = = old)
{
parent = node;
}
Node->parent = old->parent;
Node->color = old->color;
Node->right = old->right;
Node->left = old->left;
if (old->parent)
{
if (Old->parent->left = = old)
{
old->parent->left = node;
}
Else
{
old->parent->right = node;
}
}
Else
{
root = node;
}
old->left->parent = node;
if (old->right)
{
old->right->parent = node;
}
}
Else
{
if (!node->left)
{
Child = node->right;
}
else if (!node->right)
{
Child = node->left;
}
Parent = node->parent;
color = node->color;
if (child)
{
Child->parent = parent;
}
if (parent)
{
if (Parent->left = node)
{
Parent->left = child;
}
Else
{
Parent->right = child;
}
}
Else
{
root = child;
}
}
Free (old);
if (color = black)
{
root = Rb_erase_rebalance (Child, parent, root);
}
return root;
}