一、五条性质
1. Every node is either red or black.
2. The root is black.
3. Every leaf (NIL ) is black.
4. If a node is red, then both its children are black.
5. For each node, all simple paths from the node to descendant leaves contain the same number of black nodes.
二、头文件
#ifndef __IA_REDBLACK_TREE_H__
#define __IA_REDBLACK_TREE_H__
#include <common.h>
typedef struct _rb_tree_node_t {
enum _rb_tree_color{
red,
black,
} color;
int key;
struct _rb_tree_node_t *left;
struct _rb_tree_node_t *right;
struct _rb_tree_node_t *p;
} rb_tree_node_t;
typedef struct _rb_tree_t {
rb_tree_node_t *root;
rb_tree_node_t* nil;
rb_tree_node_t _nil;
}rb_tree_t;
void ia_rb_tree_init(rb_tree_t *T);
void ia_rb_tree_inorder_walk(rb_tree_t *T, rb_tree_node_t *x, FILE *f);
void ia_rb_tree_insert(rb_tree_t *T, rb_tree_node_t *z);
void ia_rb_tree_delete(rb_tree_t *T, rb_tree_node_t *z);
#endif
二、初始化及遍历
void ia_rb_tree_init(rb_tree_t *T)
{
T->nil = &T->_nil;
T->root = T->nil;
T->_nil.color = black;
T->_nil.p = T->nil;
T->_nil.left = T->nil;
T->_nil.right = T->nil;
}
void ia_rb_tree_inorder_walk(rb_tree_t *T, rb_tree_node_t *x, FILE *f)
{
const char* s_1_b = "child {\nnode [arn_b] {";
const char* s_1_r = "child {\nnode [arn_r] {";
const char* s_1_space = "child {\nnode [arn_x] {";
const char* s_2 = "}\n";
char s_v[20];
if (x != T->nil) {
if (f == NULL) {
ia_rb_tree_inorder_walk(T, x->left, f);
TRACE(" %d", x->key);
ia_rb_tree_inorder_walk(T, x->right, f);
} else {
sprintf_s(s_v, sizeof(s_v), "%d", x->key);
if (x->color == black) {
fputs(s_1_b, f);
} else {
fputs(s_1_r, f);
}
fputs(s_v, f);
fputs(s_2, f);
//print children
ia_rb_tree_inorder_walk(T, x->left, f);
ia_rb_tree_inorder_walk(T, x->right, f);
fputs(s_2, f);
}
} else {
if (f != NULL) {
fputs(s_1_space, f);
fputs(s_2, f);
fputs(s_2, f);
}
}
}
//x must not be nil
rb_tree_node_t *ia_rb_tree_minimum(rb_tree_t *T, rb_tree_node_t *x)
{
while (x->left != T->nil) {
x = x->left;
}
return x;
}
三、插入
//=========================================
// | LEFT-ROTATE(T,x) |
// (y) <--------------- (x)
// / \ / \
// (x) γ ---------------> α (y)
// / \ RIGHT-ROTATE(T,y) / \
// α β β γ
//=========================================
void ia_rb_tree_left_rotate(rb_tree_t *T, rb_tree_node_t *x)
{
//TODO: if y == T->nil ??
rb_tree_node_t *y = x->right;
x->right = y->left;
if (y->left != T->nil) {
y->left->p = x;
}
y->p = x->p;
if (x->p == T->nil) {
T->root = y;
} else if (x == x->p->left) {
x->p->left = y;
} else {
x->p->right = y;
}
y->left = x;
x->p = y;
}
void ia_rb_tree_right_rotate(rb_tree_t *T, rb_tree_node_t *y)
{
//TODO: if x == T->nil ??
rb_tree_node_t *x = y->left;
y->left = x->right;
if (x->right != T->nil) {
x->right->p = y;
}
x->p = y->p;
if (y->p == T->nil) {
T->root = x;
} else if (y == y->p->left) {
y->p->left = x;
} else {
y->p->right = x;
}
x->right = y;
y->p = x;
}
void ia_rb_tree_fixup(rb_tree_t *T, rb_tree_node_t *z)
{
rb_tree_node_t *y;
while (z->p->color == red) {
if (z->p == z->p->p->left) {
y = z->p->p->right;
if (y->color == red) {
z->p->color = black;
y->color = black;
z->p->p->color = red;
z = z->p->p;
} else {
if (z == z->p->right) {
z = z->p;
ia_rb_tree_left_rotate(T, z);
} else {
z->p->color = black;
z->p->p->color = red;
ia_rb_tree_right_rotate(T, z->p->p);
}
}
} else {
y = z->p->p->left;
if (y->color == red) {
z->p->color = black;
y->color = black;
z->p->p->color = red;
z = z->p->p;
} else {
if (z == z->p->left) {
z = z->p;
ia_rb_tree_right_rotate(T, z);
} else {
z->p->color = black;
z->p->p->color = red;
ia_rb_tree_left_rotate(T, z->p->p);
}
}
}
}
T->root->color = black;
}
void ia_rb_tree_insert(rb_tree_t *T, rb_tree_node_t *z)
{
rb_tree_node_t *y = T->nil;
rb_tree_node_t *x = T->root;
while (x != T->nil) {
y = x;
if (z->key < x->key) {
x = x->left;
} else {
x = x->right;
}
}
z->p = y;
if (y == T->nil) {
T->root = z;
} else if (z->key < y->key) {
y->left = z;
} else {
y->right = z;
}
z->left = T->nil;
z->right = T->nil;
z->color = red;
ia_rb_tree_fixup(T, z);
}
//replace u with v
void ia_rb_tree_transplant(rb_tree_t *T, rb_tree_node_t *u, rb_tree_node_t *v)
{
if (u->p == T->nil) {
T->root = v;
} else if (u == u->p->left) {
u->p->left = v;
} else {
u->p->right = v;
}
v->p = u->p;
}
void ia_rb_tree_delete_fixup(rb_tree_t *T, rb_tree_node_t *x)
{
rb_tree_node_t *w;
while (x != T->root && x->color == black) {
if (x == x->p->left) {
w = x->p->right;
if (w->color == red) {
//case 1
w->color = black;
x->p->color = red;
ia_rb_tree_left_rotate(T, x->p);
w = x->p->right;
}
if (w->left->color == black && w->right->color == black) {
//case 2
w->color = red;
x = x->p;
} else if (w->right->color == black) {
//case 3
w->left->color = black;
w->color = red;
ia_rb_tree_right_rotate(T, w);
w = x->p->right;
} else {
//case 4
w->color = x->p->color;
x->p->color = black;
w->right->color = black;
ia_rb_tree_left_rotate(T, x->p);
x = T->root;
}
} else {
w = x->p->left;
//case 1
if (w->color == red) {
w->color = black;
x->p->color = red;
ia_rb_tree_right_rotate(T, x->p);
w = x->p->left;
}
if (w->left->color == black && w->right->color == black) {
//case 2
w->color = red;
x = x->p;
} else if (w->left->color == black) {
//case 3
w->right->color = black;
w->color = red;
ia_rb_tree_left_rotate(T, w);
w = x->p->left;
} else {
//case 4
w->color = x->p->color;
x->p->color = black;
w->left->color = black;
ia_rb_tree_right_rotate(T, x->p);
x = T->root;
}
}
}
x->color = black;
}
void ia_rb_tree_delete(rb_tree_t *T, rb_tree_node_t *z)
{
rb_tree_node_t *y = z;
rb_tree_node_t *x;
enum _rb_tree_color y_original_color = z->color;
if (z->left == T->nil) {
x = z->right;
ia_rb_tree_transplant(T, z, z->right);
} else if (z->right == T->nil) {
x= z->left;
ia_rb_tree_transplant(T, z, z->left);
} else {
y = ia_rb_tree_minimum(T, z->right);
y_original_color = y->color;
x = y->right;
if (y->p == z) {
x->p = y; // x can be T->nil, and need to set parent to y
} else {
ia_rb_tree_transplant(T, y, y->right);
y->right = z->right;
y->right->p = y;
}
ia_rb_tree_transplant(T, z, y);
y->left = z->left;
y->left->p = y;
y->color = z->color;
}
if ( y_original_color == black) {
ia_rb_tree_delete_fixup(T, x);
}
}
五、脚本
create_tex.bat
rem %1 node filename, %2 out file index
type tex_head.txt > ./latex_aux/%2.tex
type %1 >> ./latex_aux/%2.tex
type tex_tail.txt >> ./latex_aux/%2.tex
pdflatex.exe --output-directory=./latex_aux --file-line-error --interaction=nonstopmode ./latex_aux/%2.tex
tex_head.txt & tex_tail.txt 请参考 http://blog.csdn.net/v2nero/article/details/17893429 中tikz脚本
#include <ia_include.h>
#define TEST_IASTACK_SIZE 10
#define TEST_IAQUEUE_SIZE 10
#define TEST_IABINARYTREE_NODES 20
void my_tree_walk(rb_tree_t *T, rb_tree_node_t *x, const char* filename)
{
FILE *f_out = NULL;
char cmd[1024];
static count = 0;
if (filename == NULL) {
ia_rb_tree_inorder_walk(T, x, NULL);
return;
}
f_out = fopen(filename, "w+");
if (f_out == NULL) {
return;
}
ia_rb_tree_inorder_walk(T, x, f_out);
fclose(f_out);
sprintf_s(cmd, sizeof(cmd), "call create_tex.bat %s %s.%02d", filename, filename,count++);
system(cmd);
//system("pause");
}
void main()
{
int i = 0;
const char * filename = "out.txt";
rb_tree_t T;
rb_tree_node_t t_nodes[TEST_IABINARYTREE_NODES];
int nodes_v[TEST_IABINARYTREE_NODES] =
{ 5, 3, 4, 8, 1, 20, 33, 30, 34, 28,
8, 33, 11, 24, 11, 10, 12, 18, 22, 23 };
/*
int nodes_v[TEST_IABINARYTREE_NODES] =
{ 5, 3, 4, 8, 1, 20, 33, 30, 34, 28,
8, 33, 11, 24, 11, 10, 12, 18, 22, 23,
10, 99, 88, 77, 20, 8, 7, 20, 3, 19};
*/
ia_rb_tree_init(&T);
memset(t_nodes, 0, sizeof(t_nodes));
for (i = 0; i < sizeof(t_nodes)/sizeof(rb_tree_node_t); ++i) {
t_nodes[i].key = nodes_v[i];
ia_rb_tree_insert(&T, &t_nodes[i]);
my_tree_walk(&T, T.root, "insert.txt");
}
my_tree_walk(&T, T.root, NULL);
my_tree_walk(&T, T.root, filename);
printf("\n\n");
//ia_rb_tree_delete(&T, &t_nodes[5]);
for (i = sizeof(t_nodes)/sizeof(rb_tree_node_t); i > 0; --i) {
ia_rb_tree_delete(&T, &t_nodes[i-1]);
my_tree_walk(&T, T.root, filename);
}
my_tree_walk(&T, T.root, NULL);
//my_tree_walk(&T, T.root, filename);
printf("\n\n");
printf("Terminated!\n");
system("pause");
}
七、结果