红黑树的实现示例(二)
本章主要给出一个红黑树的实现示例。(转自红黑树(一)之 原理和算法详细介绍)
1. 相应头文件
头文件rbtree.h
:
#ifndef __RBTREE_H_
#define __RBTREE_H_
#define RED 0x0
#define BLACK 0x1
typedef int Type;
//define red-black tree node
typedef struct RBTreeNode{
unsigned int color; //RED or BLACK
Type key;
struct RBTreeNode *left;
struct RBTreeNode *right;
struct RBTreeNode *parent;
}Node, *RBTree;
typedef struct rb_root{
Node *node;
}RBRoot;
//Create red-black tree
RBRoot *create_rbtree();
void destroy_rbtree(RBRoot **root);
//insert node to rbtree
int insert_rbtree(RBRoot *root, Type key);
//remove node from rbtree
void delete_rbtree(RBRoot *root, Type key);
void preorder_rbtree(RBRoot *root);
void inorder_rbtree(RBRoot *root);
void postorder_rbtree(RBRoot *root);
//This is the 'Recursive' version. if found key in root, then returns 0; else returns -1
int rbtree_search(RBRoot *root, Type key);
//This is the 'UnRecursive' version. If found key in root, then returns 0; else returns -1
int iterative_rbtree_search(RBRoot *root, Type key);
//find the minimum value. If found returns 0; else returns -1
int rbtree_minimum(RBRoot *root, int *value);
//find the maximum value. If found returns 0; else return -1
int rbtree_maximum(RBRoot *root, int *value);
//print the red-black tree
void print_rbtree(RBRoot *root);
#endif
2. 相应源文件
如下是源文件rbtree.c
:
#include <stdio.h>
#include <stdlib.h>
#include "rbtree.h"
#define rb_parent(r) ((r)->parent)
#define rb_color(r) ((r)->color)
#define rb_is_red(r) ((r)->color==RED)
#define rb_is_black(r) ((r)->color==BLACK)
#define rb_set_black(r) do{(r)->color = BLACK;}while(0)
#define rb_set_red(r) do{(r)->color = RED;}while(0)
#define rb_set_parent(r, p) do{(r)->parent = (p);}while(0)
#define rb_set_color(r, c) do{(r)->color = (c);}while(0)
RBRoot *create_rbtree()
{
RBRoot *root = (RBRoot *)malloc(sizeof(RBRoot));
if(root)
root->node = NULL;
return root;
}
static void preorder(RBTree tree)
{
if(tree)
{
printf("%d ", tree->key);
preorder(tree->left);
preorder(tree->right);
}
}
void preorder_rbtree(RBRoot *root)
{
if(root)
preorder(root->node);
}
static void inorder(RBTree tree)
{
if(tree)
{
inorder(tree->left);
printf("%d ", tree->key);
inorder(tree->right);
}
}
void inorder_rbtree(RBRoot *root)
{
if(root)
inorder(root->node);
}
static void postorder(RBTree tree)
{
if(tree)
{
postorder(tree->left);
postorder(tree->right);
printf("%d ", tree->key);
}
}
void postorder_rbtree(RBRoot *root)
{
if(root)
postorder(root->node);
}
static Node *search(RBTree node, Type key)
{
if(!node || node->key == key)
return node;
else if(key < node->key)
return search(node->left, key);
else
return search(node->right, key);
}
int rbtree_search(RBRoot *root, Type key)
{
if(root)
return search(root->node, key) ? 0 : -1;
}
static Node *iterative_search(RBTree node, Type key)
{
while(node && node->key != key)
{
if(key < node->key)
node = node->left;
else
node = node->right;
}
return node;
}
int iterative_rbtree_search(RBRoot * root,Type key)
{
if(root)
return iterative_search(root->node,key) ? 0 : -1;
}
//find the minimum node
static Node *minimum(RBTree tree)
{
if(!tree)
return NULL;
while(tree->left)
tree = tree->left;
return tree;
}
int rbtree_minimum(RBRoot *root, int *value)
{
Node *node = NULL;
if(root)
node = minimum(root->node);
if(!node)
return -1;
*value = node->key;
return 0x0;
}
//find the maximum
static Node *maximum(RBTree tree)
{
if(!tree)
return NULL;
while(tree->right)
tree = tree->right;
return tree;
}
int rbtree_maximum(RBRoot *root, int *value)
{
Node *node = NULL;
if(root)
node = maximum(root->node);
if(!node)
return -1;
*value = node->key;
return 0x0;
}
//find successor node
static Node *rbtree_successor(RBTree node)
{
//1) if node has right child
if(node->right)
return minimum(node->right);
//2) if node doesn't have right child, then there are the following two cases:
// 2.1) node is a 'left-child', so the successor is its parent
// 2.2) node is a 'right-child', then find the node's 'lowest parent', and the 'lowest parent' should have 'left-child',
// the founded 'lowest parent' is the node's successor
Node *p = node->parent;
while(p && (node == p->right))
{
node = p;
p = p->parent;
}
return p;
}
static Node *rbtree_predecessor(RBTree node)
{
//1) If node has left child
if(node->left)
return maximum(node->left);
//2) if node doesn't left child, then there are the following two cases:
// 2.1) node is the 'right child', so the predecessor is its parent;
// 2.2) node is the 'left child', so find the 'lowest parent', and the 'lowest parent' should have 'right child',
// the founded 'lowest parent' is the node's predecessor
Node *p = node->parent;
while(p && (node == p->left))
{
node = p;
p = p->parent;
}
return p;
}
static void rbtree_left_rotate(RBRoot *root, Node *node)
{
Node *right = node->right;
node->right = right->left;
if(right->left)
{
right->left->parent = node;
}
right->parent = node->parent;
if(node->parent)
{
if(node->parent->left == node)
node->parent->left = right;
else
node->parent->right = right;
}
else{
root->node = right;
}
right->left = node;
node->parent = right;
}
static void rbtree_right_rotate(RBRoot *root, Node *node)
{
Node *left = node->left;
node->left = left->right;
if(left->right)
{
left->right->parent = node;
}
left->parent = node->parent;
if(node->parent)
{
if(node->parent->left == node)
node->parent->left = left;
else
node->parent->right = left;
}
else{
root->node = left;
}
left->right = node;
node->parent = left;
}
static void rbtree_insert_fixup(RBRoot *root, Node *node)
{
Node *parent, *grand_parent;
while((parent = rb_parent(node)) && rb_is_red(parent))
{
grand_parent = rb_parent(parent);
if(parent == grand_parent->left)
{
Node *uncle = grand_parent->right;
//Case 1: uncle is 'red'
if(uncle && rb_is_red(uncle))
{
rb_set_black(uncle);
rb_set_black(parent);
rb_set_red(grand_parent);
node = grand_parent;
continue;
}
//Case 2: uncle is 'black', and node is a 'right' child
if(parent->right == node)
{
rbtree_left_rotate(root, parent);
Node *tmp;
tmp = parent;
parent = node;
node = tmp;
}
//Case 3: uncle is 'black', and node is a 'left' child
rb_set_black(parent);
rb_set_red(grand_parent);
rbtree_right_rotate(root, grand_parent);
}
else{
Node *uncle = grand_parent->left;
//Case 1: uncle is 'red'
if(uncle && rb_is_red(uncle))
{
rb_set_black(uncle);
rb_set_black(parent);
rb_set_red(grand_parent);
node = grand_parent;
continue;
}
//Case 2: uncle is 'black', and node is a 'left' child
if(parent->left == node)
{
rbtree_right_rotate(root, parent);
Node *tmp;
tmp = parent;
parent = node;
node = tmp;
}
//Case 3: uncle is 'black', and node is a 'right' child
rb_set_black(parent);
rb_set_red(grand_parent);
rbtree_left_rotate(root, grand_parent);
}
}
rb_set_black(root->node);
}
static void rbtree_insert(RBRoot *root, Node *node)
{
Node *p = root->node;
Node *q = NULL;
while(p)
{
q = p;
//Here not test p->key == node->key
if(node->key < p->key)
p = p->left;
else
p = p->right;
}
rb_parent(node) = q;
if(q)
{
if(node->key < q->key)
q->left = node;
else
q->right = node;
}
else{
root->node = node;
}
node->color = RED;
rbtree_insert_fixup(root, node);
}
static Node *create_rbtree_node(Type key, Node *parent, Node *left, Node *right)
{
Node *node = (Node *)malloc(sizeof(Node));
if(!node)
return NULL;
node->key = key;
node->left = left;
node->right = right;
node->color = BLACK; //Default 'BLACK'
return node;
}
int insert_rbtree(RBRoot *root, Type key)
{
Node *node = NULL;
if(search(root->node,key) != NULL)
return -1;
if((node = create_rbtree_node(key, NULL, NULL, NULL)) == NULL)
return -1;
rbtree_insert(root, node);
return 0x0;
}
static void rbtree_delete_fixup(RBRoot *root, Node *node, Node *parent)
{
Node *brother;
while((!node || rb_is_black(node)) && node != root->node)
{
if(parent->left == node)
{
brother = parent->right;
if(rb_is_red(brother))
{
//Case 1: brother is 'red'
rb_set_black(brother);
rb_set_red(parent);
rbtree_left_rotate(root, parent);
brother = parent->right;
}
if((!brother->left || rb_is_black(brother->left)) &&
(!brother->right || rb_is_black(brother->right)))
{
//Case 2: brother is 'black', and brother's two children are color-black
rb_set_red(brother);
node = parent;
parent = rb_parent(node);
}
else{
if(!brother->right || rb_is_black(brother->right))
{
//Case 3: brother is 'black', and brother's left child is color-red, brother's right child is color-black
rb_set_black(brother->left);
rb_set_red(brother);
rbtree_right_rotate(root, brother);
brother = parent->right;
}
//Case 4: brother is 'black' , and brother's right child is color-red, brother's left child is any-color
rb_set_color(brother, rb_color(parent));
rb_set_black(parent);
rb_set_black(brother->right);
rbtree_left_rotate(root, parent);
node = root->node;
break;
}
}
else{
brother = parent->left;
if(rb_is_red(brother))
{
//Case 1: brother is 'red'
rb_set_black(brother);
rb_set_red(parent);
rbtree_right_rotate(root, parent);
brother = parent->left;
}
if((!brother->left || rb_is_black(brother->left)) &&
(!brother->right || rb_is_black(brother->right)))
{
//Case 2: brother is 'black', and brother's two children is color-black
rb_set_red(brother);
node = parent;
parent = rb_parent(node);
}
else{
if(!brother->left || rb_is_black(brother->left))
{
//Case 3: brother is 'black', and brother's left child is color-black, brother's right child is color-red
rb_set_black(brother->right);
rb_set_red(brother);
rbtree_left_rotate(root, brother);
brother = parent->left;
}
//Case 4: brother is 'black', and brother's left child is color-red, brother's right child is any-color
rb_set_color(brother, rb_color(parent));
rb_set_black(parent);
rb_set_black(brother->left);
rbtree_right_rotate(root,parent);
node = root->node;
break;
}
}
}
if(node)
rb_set_black(node);
}
static void rbtree_delete(RBRoot *root, Node *node)
{
Node *child;
Node *parent;
int color;
if(node->left && node->right)
{
//find its's successor node
Node *replace = node->right;
while(replace->left)
replace = replace->left;
if(rb_parent(node))
{
if(rb_parent(node)->left == node)
rb_parent(node)->left = replace;
else
rb_parent(node)->right = replace;
}
else{
//node is the root
root->node = replace;
}
// 'child' is node-replace's right child
child = replace->right;
parent = rb_parent(replace);
color = replace->color; //save the color
if(parent == node)
{
parent = replace;
}
else{
//child is NOT NULL
if(child)
rb_set_parent(child, parent);
parent->left = child;
replace->right = node->right;
rb_set_parent(node->right, replace);
}
replace->parent = node->parent;
replace->color = node->color;
replace->left = node->left;
node->left->parent = replace;
if(color == BLACK)
rbtree_delete_fixup(root, child, parent);
free(node);
return;
}
if(node->left)
child = node->left;
else
child = node->right;
parent = node->parent;
color = node->color; //save the color
if(child)
child->parent = parent;
if(parent)
{
if(parent->left == node)
parent->left = child;
else
parent->right = child;
}
else{
root->node = child;
}
if(color == BLACK)
rbtree_delete_fixup(root, child, parent);
free(node);
}
void delete_rbtree(RBRoot *root, Type key)
{
Node *node;
if((node = search(root->node, key)) != NULL)
{
rbtree_delete(root, node);
return;
}
}
static void rbtree_destroy(RBTree tree)
{
if(!tree)
return;
rbtree_destroy(tree->left);
rbtree_destroy(tree->right);
free(tree);
}
void destroy_rbtree(RBRoot **root)
{
if(!*root)
return;
rbtree_destroy((*root)->node);
(*root)->node = NULL;
free(*root);
*root = NULL;
}
static void rbtree_print(RBTree tree, Type key, int direction)
{
if(tree != NULL)
{
if(direction == 0) //tree is 'root' node
printf("%2d(B) is root\n", tree->key);
else
printf("%2d(%s) is %2d's %6s child\n", tree->key, rb_is_red(tree) ? "R" : "B", key, direction == 1 ? "right" : "left");
rbtree_print(tree->left,tree->key, -1);
rbtree_print(tree->right, tree->key, 1);
}
}
void print_rbtree(RBRoot *root)
{
if(root && root->node)
rbtree_print(root->node, root->node->key, 0x0);
}
3. 测试源文件
如下是测试源文件main.c
:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "rbtree.h"
#define CHECK_INSERT 0x0
#define CHECK_DELETE 0x0
#define LENGTH(a) ((sizeof(a)/sizeof(a[0])))
int main(int argc,char *argv[])
{
int a[] = {10,40, 30, 60, 90, 70, 20, 50, 80};
int i, length;
RBRoot *root = NULL;
length = LENGTH(a);
if((root = create_rbtree()) == NULL)
{
printf("memory allocation failure\n");
return -1;
}
printf("== origin data:");
for(i = 0;i<length;i++)
printf("%d ", a[i]);
printf("\n");
for(i = 0;i<length; i++)
{
insert_rbtree(root, a[i]);
#if CHECK_INSERT
printf("== add node: %d\n", a[i]);
printf("== rbtree detail:\n");
print_rbtree(root);
printf("\n");
#endif
}
printf("== preorder:");
preorder_rbtree(root);
printf("\n== inorder:");
inorder_rbtree(root);
printf("\n== postorder: ");
postorder_rbtree(root);
printf("\n");
if(rbtree_minimum(root, &i) == 0)
printf("== minimum value: %d\n", i);
if(rbtree_maximum(root, &i) == 0)
printf("== maximum value: %d\n", i);
printf("== rbtree detail: \n");
print_rbtree(root);
printf("\n");
#if CHECK_DELETE
for(i = 0;i<length;i++)
{
delete_rbtree(root, a[i]);
printf("== remove node: %d\n", a[i]);
if(root)
{
printf("== rbtree detail:\n");
print_rbtree(root);
printf("\n");
}
}
#endif
destroy_rbtree(&root);
return 0x0;
}
编译运行:
# gcc -o rbtree *.c # ./rbtree == origin data:10 40 30 60 90 70 20 50 80 == preorder:30 10 20 60 40 50 80 70 90 == inorder:10 20 30 40 50 60 70 80 90 == postorder: 20 10 50 40 70 90 80 60 30 == minimum value: 10 == maximum value: 90 == rbtree detail: 30(B) is root 10(B) is 30's left child 20(R) is 10's right child 60(R) is 30's right child 40(B) is 60's left child 50(R) is 40's right child 80(B) is 60's right child 70(R) is 80's left child 90(R) is 80's right child
[参看]: