//本工程在visual studio下能看完整的图,利用graphviz作图工具,保证graphviz添加到环境变量中
#include <stdio.h>
#include <stdlib.h>
typedef struct rbnode{
int key;
char color;
struct rbnode *parent;
struct rbnode *left;
struct rbnode *right;
}rbnode_t;
//定义根和nil节点
rbnode_t *nil, *root;
//右旋
/*
* x y
* / \ / \
* y c --> a x
* / \ / \
* a b b c
*
*/
void right_rotate(rbnode_t *x){
//右旋以x和x的左儿子为轴进行旋转
rbnode_t *y = x->left;
x->left = y->right;
if(y->right != nil)
y->right->parent = x;
y->parent = x->parent;
if(x->parent == nil)
root = y;
else if(x == x->parent->left)
x->parent->left = y;
else
x->parent->right = y;
x->parent = y;
y->right = x;
}
/**
* 左旋,以x和x的右节点为轴进行旋转
* x y
* / \ / \
* a y ---> x c
* / \ / \
* b c a b
*/
void left_rotate(rbnode_t *node){
rbnode_t *y = node->right;
node->right = y->left;
if(y->left != nil)
y->left->parent = node;
y->parent = node->parent;
if(node->parent == nil){
root = y;
}else if(node == node->parent->left){
node->parent->left = y;
}else{
node->parent->right = y;
}
y->left = node;
node->parent = y;
}
/**
节点插入后,红黑树的查找性质m没有被破坏,但是红黑性质被破坏.该函数调整红黑性质
*/
void adjust_tree(rbnode_t *node){
while(node->parent->color == 'r'){
if(node->parent == node->parent->parent->left){
rbnode_t *y = node->parent->parent->right;
/**
* 如果node父亲b是祖父a的左孩子,并且叔叔c是黑色,那么变换如下
* a(b) node->a(r) :祖父节点变红
* / \ / \
* b(r) c(r) ---> b(b) c(b) :父亲和叔叔变黑
* / /
* node-> d(r) d(r) :当前指针晚上移到祖父节点
* :祖父节点b变为新的node节点
* r表示红色,b表示黑色
*/
if(y->color == 'r'){
node->parent->color = 'b';
y->color = 'b';
node->parent->parent->color = 'r';
node = node->parent->parent;
}
else
{
/**
* 如果node的叔叔是黑色,当前节点node是其父亲的右孩子,那么当前节点上移一位,然后在当前节点执行左旋转
* a(r) a(r)
* / \ / \
* b(r) c(b) ---> d(r) c(b)
* \ /
* node-> d(r) b(r) <-node
*
* 简单理解就是旋转使得当前节点(b)和其父节点(d)以及祖父节点(a)成一条线,然后转为下面这种情况执行右旋
*/
if(node == node->parent->right){
node = node->parent;
left_rotate(node);
}
/**
* 把当前节点父节点涂成黑色,祖父节点涂成红色,右旋其祖父节点a
* a(b) b(b)
* / \ / \
* b(r) c(b) ---> d(r) a(r)
* / \
* node-> d(r) c(b)
*
*/
node->parent->color = 'b';
node->parent->parent ->color = 'r';
node = node->parent->parent;
right_rotate(node);
}
}else{
/**
* 当前节点父亲是其祖父的右孩子时,与上面分析对称
*/
rbnode_t *y = node->parent->parent->left;
if(y->color == 'r'){
node->parent->color = 'b';
y->color = 'b';
node->parent->parent->color = 'r';
node = node->parent->parent;
}
else{
if(node == node->parent->left){
node = node->parent;
right_rotate(node);
}
node->parent->color = 'b';
node->parent->parent->color = 'r';
node = node->parent->parent;
left_rotate(node);
}
}
}
root->color = 'b';
}
void insert(int key){
rbnode_t *parent = nil, *point = root;
while(point != nil){
parent = point;
if(key < point->key)
point = point->left;
else
point = point->right;
}
rbnode_t *node = (rbnode_t*)malloc(sizeof(rbnode_t));
node->key = key;
node->color = 'r';
node->left = nil;
node->right = nil;
node->parent = parent;
if(parent == nil)
root = node;
else if(key < parent->key)
parent->left = node;
else
parent->right = node;
adjust_tree(node);
}
void build_tree(int *array, int size){
nil = (rbnode_t*)malloc(sizeof(rbnode_t));
nil->color = 'b';
nil->left = nil->right = nil->parent = NULL;
nil->key = 0;
root = nil;
for(int i = 0; i < size; ++i){
insert(array[i]);
}
}
FILE *fp;
void dfs(rbnode_t *node){
fprintf(fp, "\t%d[color=%s];\n", node->key, node->color == 'r' ? "red" : "black");
if(node->left != nil){
fprintf(fp, "\t%d->%d;\n", node->key, node->left->key);
dfs(node->left);
}
if(node->right != nil){
fprintf(fp, "\t%d->%d;\n", node->key, node->right->key);
dfs(node->right);
}
}
void print_tree(){
fp = fopen("test.dot", "w");
fprintf(fp, "digraph G {\n");
dfs(root);
fprintf(fp, "}");
fclose(fp);
system("dot -Tpng -o test.png test.dot");
system("start test.png");
}
rbnode_t *tree_minmun(rbnode_t *x){
while(x->left != nil)
x = x->left;
return x;
}
rbnode_t *successor(rbnode_t *x){
rbnode_t *y;
if(x->right != nil)
return tree_minmun(x->right);
y = x->parent;
while(y != nil && x == y->right){
x = y;
y = y->parent;
}
return y;
while(x->left != nil){
y = x;
x = x->left;
}
return y;
}
void delete_fixup(rbnode_t *x){
while(x != root && x->color == 'b'){
rbnode_t *w;
if(x == x->parent->left){
w = x->parent->right;
if(w->color == 'r'){
w->color = 'b';
w->parent->color = 'r';
left_rotate(x->parent);
w = x->parent->right;
}
if(w->left->color == 'b' && w->right->color == 'b'){
w->color = 'r';
x = x->parent;
}
else{
if(w->right->color == 'b'){
w->left->color = 'b';
w->color = 'r';
right_rotate(w);
w = x->parent->right;
}
w->color = x->parent->color;
x->parent->color = 'b';
w->right->color = 'b';
left_rotate(x->parent);
x = root;
}
}
else{
w = x->parent->left;
if(w->color == 'r'){
w->color = 'b';
w->parent->color = 'r';
right_rotate(x->parent);
w = x->parent->left;
}
if(w->left->color == 'b' && w->right->color == 'b'){
w->color = 'r';
x = x->parent;
}
else{
if(w->left->color == 'b'){
w->right->color = 'b';
w->color = 'r';
left_rotate(w);
w = x->parent->left;
}
w->color = x->parent->color;
x->parent->color = 'b';
w->left->color = 'b';
right_rotate(x->parent);
x = root;
}
}
}
x->color = 'b';
}
void rb_delete(rbnode_t *z){
rbnode_t *y, *x;
if(z->left == nil || z->right == nil)
y = z;
else
y = successor(z);
if(y->left != nil)
x = y->left;
else
x = y->right;
x->parent = y->parent;
if(y->parent == nil)
root = x;
else if(y == y->parent->left)
y->parent->left = x;
else
y->parent->right = x;
if(y != z)
z->key = y->key;
if(y->color == 'b')
delete_fixup(x);
}
rbnode_t *rb_find(int key){
rbnode_t *x = root;
while(x != nil){
if(key < x->key){
x = x->left;
}else if(key > x->key){
x = x->right;
}else{
return x;
}
}
}
int main(int argc, char const *argv[])
{
int array[] = {12, 1, 9, 2, 0, 11, 7, 19, 4, 15, 18, 5, 14, 13, 10, 16, 6, 3, 8, 17};
int size = sizeof(array)/sizeof(array[0]);
build_tree(array, size);
print_tree();
for(int i = 0; i < size - 1; ++i){
rbnode_t *node = rb_find(array[i]);
rb_delete(node);
print_tree();
}
return 0;
}
红黑树的插入和删除
最新推荐文章于 2022-06-06 20:09:57 发布