"""
.h头文件
代码基本依据<<算法导论>>的伪代码编写.
代码在mac环境下使用gcc编译器运行良好
"""
1 #ifndef RB_TREE_H__
2 #define RB_TREE_H__
3
4 #define NAGETIVE_INFINITY -100000000
5 #define INFINITY 100000000
6
7 typedef enum {RED, BLACK} colorType;
8
9 typedef struct redBlackNode * redBlackTree;
10 typedef struct redBlackNode * position;
11
12 struct redBlackNode
13 {
14 int val;
15 redBlackTree left;
16 redBlackTree right;
17 redBlackTree parent;
18 colorType color;
19 };
20
21 // init nullNode and return a sign node
22 redBlackTree init(void);
23 // free memory
24 void disposeTree(redBlackTree t);
25 // in-order traversal and output to stdout
26 void inOrderTraversal(redBlackTree t);
27 // insert a node
28 void insertNode(int x, redBlackTree t);
29 // delete a node
30 void deleteNode(int x, redBlackTree t);
31
32 #endif """.c源文件"""
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <assert.h>
#include "rb_tree.h"
position nullNode = NULL; // 用于代替NULL节点作为标识
static void test_insert(redBlackTree root, int n);
static void test_delete(redBlackTree root, int n, char *input, char *output);
inline static void memoryApplyError()
{
fprintf(stderr, "apply memory fail\n");
exit(1);
}
// left rotate.
// pay attention to handling t->parent relationship when rotating
static void singleLeftRotate(redBlackTree x, redBlackTree t)
{
redBlackTree y, z;
y = x->right;
x->right = y->left;
if (y->left != nullNode)
y->left->parent = x;
y->parent = x->parent;
if (x->parent == t)
t->right = y;
else if (x == x->parent->left)
x->parent->left = y;
else
x->parent->right = y;
x->parent = y;
y->left = x;
}
// right rotate.
// pay attention to handling t->parent relationship when rotating
static void singleRightRotate(redBlackTree x, redBlackTree t)
{
redBlackTree y, z;
y = x->left;
x->left = y->right;
if (y->right != nullNode)
y->right->parent = x;
y->parent = x->parent;
if (x->parent == t)
t->right = y;
else if (x == x->parent->left)
x->parent->left = y;
else
x->parent->right = y;
x->parent = y;
y->right = x;
}
// if the uncle node is red and this is the case 1
static redBlackTree redUncle(redBlackTree child, redBlackTree uncle)
{
uncle->color = child->parent->color = BLACK;
child->parent->parent->color = RED;
child = child->parent->parent;
return child;
}
// hanle the case that parent node is in the left subtree of the grandparent node
static redBlackTree handelInsertLeftCase(redBlackTree child, redBlackTree t)
{
redBlackTree uncle;
uncle = child->parent->parent->right;
if (uncle->color == RED) {
child = redUncle(child, uncle);
} else
{
// child node is child->left->right; first left rotate;
if (child == child->parent->right)
{
child = child->parent;
singleLeftRotate(child, t);
}
child->parent->color = BLACK;
child->parent->parent->color = RED;
singleRightRotate(child->parent->parent, t);
}
return child;
}
// handle the case that parent node is in the right subtree of the grandparent node
static redBlackTree handleInsertRightCase(redBlackTree child, redBlackTree t)
{
redBlackTree uncle;
uncle = child->parent->parent->left;
if (uncle->color == RED) {
child = redUncle(child, uncle);
} else
{
// child node is grandparent->right->left; first to right rotate
if (child == child->parent->left)
{
child = child->parent;
singleRightRotate(child, t);
}
child->parent->color = BLACK;
child->parent->parent->color = RED;
singleLeftRotate(child->parent->parent, t);
}
return child;
}
static redBlackTree handleDeleteLeftCase(redBlackTree target, redBlackTree t)
{
redBlackTree brother;
brother = target->parent->right;
if (brother->color == RED)
{
brother->color = BLACK;
target->parent->color = RED;
singleLeftRotate(target->parent, t);
brother = target->parent->right;
}
if (brother->color == BLACK && brother->left->color == BLACK && brother->right->color == BLACK)
{
brother->color = RED;
target = target->parent;
}
else if (brother->color == BLACK)
{
if (brother->left->color == RED && brother->right->color == BLACK)
{
brother->color = RED;
brother->left->color = BLACK;
singleRightRotate(brother, t);
brother = target->parent->right;
}
brother->color = target->parent->color;
target->parent->color = BLACK;
brother->right->color = BLACK;
singleLeftRotate(target->parent, t);
t->left = target;
}
return target;
}
static redBlackTree handleDeleteRightCase(redBlackTree target, redBlackTree t)
{
redBlackTree brother;
brother = target->parent->left;
if (brother->color == RED)
{
brother->color = BLACK;
target->parent->color = RED;
singleRightRotate(target->parent, t);
brother = target->parent->left;
}
if (brother->color == BLACK && brother->left->color == BLACK && brother->right->color == BLACK)
{
brother->color = RED;
target = target->parent;
}
else
{
if (brother->right->color == RED && brother->left->color == BLACK)
{
brother->color = RED;
brother->right->color = BLACK;
singleLeftRotate(brother, t);
brother = target->parent->left;
}
brother->color = target->parent->color;
target->parent->color = BLACK;
brother->left->color = BLACK;
singleRightRotate(target->parent, t);
t->left = target;
}
return target;
}
static redBlackTree findMin(redBlackTree target)
{
while (target->left != nullNode)
target = target->left;
return target;
}
static void disposeRealTree(redBlackTree t)
{
if (t != nullNode)
{
disposeRealTree(t->left);
disposeRealTree(t->right);
free(t);
}
}
// repair red-black tree.
static void insertFixUp(redBlackTree child, redBlackTree t)
{
redBlackTree uncle;
while (child->parent->color == RED) {
// parent node is in the left subtree of the grandparent node
if (child->parent == child->parent->parent->left) {
child = handelInsertLeftCase(child, t);
} else { // parent node is in the right subtree of the grandparent node
child = handleInsertRightCase(child, t);
}
}
t->right->color = BLACK;
}
static redBlackTree rbTransplant(redBlackTree t, redBlackTree origin, redBlackTree target)
{
if (origin->parent == t) {
t->right = target;
target->color = BLACK;
target->parent = t;
} else if (origin == origin->parent->left) {
origin->parent->left = target;
target->parent = origin->parent;
} else {
origin->parent->right = target;
target->parent = origin->parent;
}
return target;
}
static void deleteFixup(redBlackTree t, redBlackTree target)
{
redBlackTree parent;
while ((t->left == target || t->right == target) && target->color == BLACK) {
parent = target->parent;
// target on the left subtree of the parent node
if (target == parent->left) {
target = handleDeleteLeftCase(target, t);
} else { // target on the right subtree of the parent node
target = handleDeleteRightCase(target, t);
}
}
t->left = nullNode;
target->color = BLACK;
}
// create a new tree
redBlackTree init(void)
{
if (nullNode == NULL)
{
nullNode = malloc(sizeof(struct redBlackNode));
if (nullNode == NULL)
memoryApplyError();
nullNode->left = nullNode->right = nullNode->parent = nullNode;
nullNode->color = BLACK;
}
redBlackTree t;
t = malloc(sizeof(struct redBlackNode));
if (t == NULL)
memoryApplyError();
t->val = NAGETIVE_INFINITY;
t->color = BLACK;
t->left = t->right = t->parent = nullNode;
return t;
}
void insertNode(int val, redBlackTree t)
{
redBlackTree child, parent, grandparent, newNode;
child = t->right;
parent = nullNode;
newNode = malloc(sizeof(struct redBlackNode));
if (newNode == NULL)
memoryApplyError();
newNode->val = val;
newNode->color = RED;
newNode->left = newNode->right = nullNode;
while (child != nullNode) {
parent = child;
if (val == child->val)
return;
else if (val < child->val)
child = child->left;
else
child = child->right;
}
if (parent == nullNode) {
newNode->color = BLACK;
t->right = newNode;
newNode->parent = t;
return;
}
newNode->parent = parent;
if (newNode->val < parent->val)
parent->left = newNode;
else
parent->right = newNode;
insertFixUp(newNode, t);
}
void deleteNode(int val, redBlackTree t)
{
colorType originalColor;
redBlackTree target, replace, minNode;
target = t->right;
while (val != target->val) {
if (val < target->val)
target = target->left;
else
target = target->right;
}
if (target == nullNode)
return ;
originalColor = target->color;
if (target->left == nullNode) {
replace = rbTransplant(t, target, target->right);
free(target);
} else if (target->right == nullNode) {
replace = rbTransplant(t, target, target->left);
free(target);
} else {
minNode = findMin(target->right);
originalColor = minNode->color;
target->val = minNode->val;
replace = rbTransplant(t, minNode, minNode->right);
free(minNode);
}
if (originalColor == BLACK)
deleteFixup(t, replace);
}
static void realInOrderTraversal(redBlackTree t)
{
assert(t != NULL);
if (t != nullNode)
{
inOrderTraversal(t->left);
fprintf(stdout, "val-> %d parent->val = %d color->%s \n", t->val, t->parent->val, t->color == RED ? "red" : "black");
inOrderTraversal(t->right);
}
}
void inOrderTraversal(redBlackTree t)
{
realInOrderTraversal(t->right);
}
void disposeTree(redBlackTree t)
{
disposeRealTree(t->right);
free(t);
}