说起红黑树,最头疼的就是插入或删除后引起的不平衡,各种旋转,着色细节让人难以理解。我一开始是网上找别人的代码来看,看的一头雾水,还是算法导论上的的伪代码到位,不用纠结于各种细节,虽然我现在依然没有彻底搞清楚,但是根据书上的伪代码写了一遍,居然也能通过验证。
这里不做深入分析,只要对红黑树有个大概的了解,相信书上的算法就好。对插入和删除要做哪些事情大体了解下,不用探究细节。不废话,直接上代码,我的一些理解写在了代码注释中
更新一下,删除节点在remove_rbt_node方法末尾,在执行待删除节点与他右子树最左边的节点交换后,调用free,这点算法导论书上没有写出
调试中输出了涉及旋转、交换的节点的值,直观的感受插入和删除操作的过程
头文件
/*
* File: rb_tree.h
* Author: weng
*
* Created on 2018年11月8日, 下午9:40
*/
#ifndef RB_TREE_H
#define RB_TREE_H
#ifdef __cplusplus
extern "C" {
#endif
#define DEBUG_RBT 1
typedef int RBTKey;
enum rbt_color {
RED = 0, BLACK
};
struct rbt_node {
struct rbt_node* parent;
struct rbt_node* left;
struct rbt_node* right;
RBTKey key;
enum rbt_color color;
};
struct rb_tree {
struct rbt_node* root;
struct rbt_node* nil;
};
typedef struct rbt_node RBTNode;
typedef struct rb_tree RBTree;
/*
* 常用方法
*/
RBTree* create_rbtree(void); //使用malloc在堆中创建红黑树并初始化
RBTree* init_rbtree(RBTree* t); //初始化
RBTree* insert_rbt_node(RBTree* t, const RBTKey key); //插入key
RBTree* remove_rbt_node(RBTree* t, const RBTKey key); //删除key对应节点
void clear_rbtree(RBTree* t); //后序遍历,free树中的节点,对于t需要另行处理
void display_rbt(RBTree* t); //中序遍历
void display_rbt_prevorder(RBTree* t); //先序遍历
void display_rbt_postorder(RBTree* t); //后序遍历
void show_rbt(RBTree* t); //图示
/*
* 辅助函数
* 参数中RBTree* t, RBTNode* r
* t->root为根节点, r为待操作的节点
*/
RBTNode* create_rbt_node(const RBTKey key); //使用malloc在堆中创建节点并初始化
RBTree* rbt_insert_fixup(RBTree* t, RBTNode* r); //插入后平衡
RBTree* rbt_left_rotate(RBTree* t, RBTNode* r); //左旋
RBTree* rbt_right_rotate(RBTree* t, RBTNode* r); //右旋
RBTree* rbt_transplant(RBTree* t, RBTNode* u, RBTNode* v); //互换节点
RBTree* rbt_delete_fixup(RBTree* t, RBTNode* r); //删除后平衡
RBTNode* rbt_minimum(RBTree* t, RBTNode* r); //返回将与待删除节点互换的节点 \
//这里是用待删除节点的右孩子的最左边一个节点与待删除节点互换,使得他们位置变换, \
//然后执行删除,这样树的整体结构不变,之后执行平衡策略
void clear_rbt_node_post(RBTree* t, RBTNode* r);
void display_rbt_node(RBTree* t, RBTNode* r);
void display_rbt_node_prev(RBTree* t, RBTNode* r);
void display_rbt_node_post(RBTree* t, RBTNode* r);
void show_rbt_node(RBTree* t, RBTNode* r, int high, int n); //
#ifdef __cplusplus
}
#endif
#endif /* RB_TREE_H */
方法实现源文件
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
#include "rb_tree.h"
#include <stdio.h>
#include <stdlib.h>
RBTree* create_rbtree(void) {
RBTree* t = (RBTree*) malloc(sizeof (RBTree));
/*
t->nil = create_rbt_node(0);
t->nil->color = BLACK;
t->root = t->nil;
return t;
*/
init_rbtree(t);
return t;
}
RBTree* init_rbtree(RBTree* t) {
t->nil = create_rbt_node(0);
t->nil->color = BLACK;
t->root = t->nil;
return t;
}
RBTree* insert_rbt_node(RBTree* t, const RBTKey key) {
RBTNode* rp = t->root; //插入路径上的迭代器//书上记作x
RBTNode* parent = t->nil; //迭代器的父节点//y
/*
RBTNode* r = create_rbt_node(key); //待插入的节点//z
*/
while (rp != t->nil) {
parent = rp;
if (key < rp->key)
rp = rp->left;
else if (key > rp->key)
rp = rp->right;
else
return t; //树中已有key,返回
}
RBTNode* r = create_rbt_node(key); //待插入的节点//z
r->parent = parent;
r->left = t->nil;
r->right = t->nil;
if (parent == t->nil)
t->root = r;
else if (key < parent->key)
parent->left = r;
else
parent->right = r;
t = rbt_insert_fixup(t, r);
return t;
}
RBTree* remove_rbt_node(RBTree* t, const RBTKey key) {
RBTNode* rp = t->root; //删除路径上的迭代器//y
while (rp != t->nil) {
if (key < rp->key)
rp = rp->left;
else if (key > rp->key)
rp = rp->right;
else
break; //找到key
}
if (rp == t->nil)
return t; //未找到
RBTNode* z = rp; //z 待删除key的节点
enum rbt_color y_o_c = rp->color; //记录颜色
RBTNode* x; //记录z的孩子节点
if (z->left == t->nil) {
x = z->right;
rbt_transplant(t, z, z->right);
} else if (z->right == t->nil) {
x = z->left;
rbt_transplant(t, z, z->left);
} else {
rp = rbt_minimum(t, z->right);
/*
//以下4行为tree_minimum方法
rp = z->right;
while (rp->left != t->nil) {
rp = rp->left;
}
*/
y_o_c = rp->color;
x = rp->right;
if (rp->parent == z)
x->parent = rp;
else {
rbt_transplant(t, rp, rp->right);
rp->right = z->right;
rp->right->parent = rp;
}
rbt_transplant(t, z, rp);
rp->left = z->left;
rp->left->parent = rp;
rp->color = z->color;
}
#ifdef DEBUG_RBT
printf("删除节点 %d\n", u->key);
#endif
free(z);//删除节点
if (y_o_c == BLACK)
rbt_delete_fixup(t, x);
}
void clear_rbtree(RBTree* t) {
if (t == NULL)return;
clear_rbt_node_post(t, t->root);
if (t->nil != NULL)
free(t->nil);
}
void display_rbt(RBTree* t) {
if (t == NULL)return;
display_rbt_node(t, t->root);
printf("\n");
}
void display_rbt_prevorder(RBTree* t) {
if (t == NULL)return;
display_rbt_node_prev(t, t->root);
printf("\n");
}
void display_rbt_postorder(RBTree* t) {
if (t == NULL)return;
display_rbt_node_post(t, t->root);
printf("\n");
}
void show_rbt(RBTree* t) {
if (t == NULL)return;
int h = 0;
int n = 0;
show_rbt_node(t, t->root, h, n);
}
RBTNode* create_rbt_node(const RBTKey key) {
RBTNode* r = (RBTNode*) malloc(sizeof (RBTNode));
r->left = r->right = r->parent = NULL;
r->color = RED;
r->key = key;
return r;
}
/*
* 参数中RBTree* t, RBTNode* r
* t->root为根节点, r为待操作的节点
*/
RBTree* rbt_insert_fixup(RBTree* t, RBTNode* r) {
while (r->parent->color == RED) {
if (r->parent == r->parent->parent->left) {
RBTNode* u = r->parent->parent->right; //r的叔叔uncle;//y
if (u->color == RED) {//case 1
r->parent->color = BLACK;
u->color = BLACK;
r->parent->parent->color = RED;
r = r->parent->parent;
} else if (r == r->parent->right) {//case 2
r = r->parent;
rbt_left_rotate(t, r);
} else {//case 3//第三版书上这里没有else,加上
r->parent->color = BLACK;
r->parent->parent->color = RED;
rbt_right_rotate(t, r->parent->parent);
}
} else {
RBTNode* u = r->parent->parent->left; //r的叔叔uncle;//y
if (u->color == RED) {
r->parent->color = BLACK;
u->color = BLACK;
r->parent->parent->color = RED;
r = r->parent->parent;
} else if (r == r->parent->left) {
r = r->parent;
rbt_right_rotate(t, r);
} else {//
r->parent->color = BLACK;
r->parent->parent->color = RED;
rbt_left_rotate(t, r->parent->parent);
}
}
}//while
t->root->color = BLACK;
return t;
}
RBTree* rbt_left_rotate(RBTree* t, RBTNode* r) {
if (r->right != t->nil) {
RBTNode* child = r->right; //y
#ifdef DEBUG_RBT
printf("left_rolate %d<->%d\n", r->key, child->key);
#endif
r->right = child->left;
if (child->left != t->nil)
child->left->parent = r;
child->parent = r->parent;
if (r->parent == t->nil)
t->root = child;
else if (r == r->parent->left)
r->parent->left = child;
else
r->parent->right = child;
child->left = r;
r->parent = child;
}
return t;
}
RBTree* rbt_right_rotate(RBTree* t, RBTNode* r) {
if (r->left != t->nil) {//书上伪代码之前假设这个条件,
//根节点的父节点为nil已经在init_rbtree()方法中初始化
RBTNode* child = r->left; //y
#ifdef DEBUG_RBT
printf("right_rolate %d<->%d\n", r->key, child->key);
#endif
r->left = child->right;
if (child->right != t->nil)
child->right->parent = r;
child->parent = r->parent;
if (r->parent == t->nil)
t->root = child;
else if (r == r->parent->right)
r->parent->right = child;
else
r->parent->left = child;
child->right = r;
r->parent = child;
}
return t;
}
RBTree* rbt_transplant(RBTree* t, RBTNode* u, RBTNode* v) {
if (u->parent == t->nil)
t->root = v;
else if (u == u->parent->left)
u->parent->left = v;
else
u->parent->right = v;
v->parent = u->parent;
#ifdef DEBUG_RBT
printf("transplant %d %d\n", u->key, v->key);
#endif
return t;
}
RBTree* rbt_delete_fixup(RBTree* t, RBTNode* x) {//r=x
while (x != t->root && x->color == BLACK) {
RBTNode* w; //记录x的兄弟节点
if (x == x->parent->left) {
w = x->parent->right;
if (w->color == RED) {//case 1
w->color = BLACK;
x->parent->color = RED;
rbt_left_rotate(t, x->parent);
w = x->parent->right;
}
if (w->left->color == BLACK && w->right->color == BLACK) {//case 2
w->color = RED;
x = x->parent;
} else if (w->right->color == BLACK) {//case 3
w->left->color = BLACK;
w->color = RED;
rbt_right_rotate(t, w);
w = x->parent->right;
} else {//else一定要加上//case 4
w->color = x->parent->color; //case 4
x->parent->color = BLACK;
w->right->color = BLACK;
rbt_left_rotate(t, x->parent);
x = t->root;
}
} else {//镜像
w = x->parent->left;
if (w->color == RED) {//case 1
w->color = BLACK;
x->parent->color = RED;
rbt_right_rotate(t, x->parent);
w = x->parent->left;
}
if (w->right->color == BLACK && w->left->color == BLACK) {//case 2
w->color = RED;
x = x->parent;
} else if (w->left->color == BLACK) {//case 3
w->right->color = BLACK;
w->color = RED;
rbt_left_rotate(t, w);
w = x->parent->left;
} else {
w->color = x->parent->color; //case 4
x->parent->color = BLACK;
w->left->color = BLACK;
rbt_right_rotate(t, x->parent);
x = t->root;
}
}
}//while
x->color = BLACK;
}
RBTNode* rbt_minimum(RBTree* t, RBTNode* r) {
while (r->left != t->nil) {
r = r->left;
}
return r;
}
void clear_rbt_node_post(RBTree* t, RBTNode* r) {
if (r != t->nil) {
clear_rbt_node_post(t, r->left);
clear_rbt_node_post(t, r->right);
if (r != NULL)
free(r);
}
}
void display_rbt_node(RBTree* t, RBTNode* r) {
if (r != t->nil) {
display_rbt_node(t, r->left);
/*
printf("%d\n", r->key);
*/
printf("%d ", r->key);
display_rbt_node(t, r->right);
}
}
void display_rbt_node_prev(RBTree* t, RBTNode* r) {
if (r != t->nil) {
/*
printf("%d\n", r->key);
*/
printf("%d ", r->key);
display_rbt_node_prev(t, r->left);
display_rbt_node_prev(t, r->right);
}
}
void display_rbt_node_post(RBTree* t, RBTNode* r) {
if (r != t->nil) {
display_rbt_node_post(t, r->left);
display_rbt_node_post(t, r->right);
/*
printf("%d\n", r->key);
*/
printf("%d ", r->key);
}
}
void show_rbt_node(RBTree* t, RBTNode* r, int high, int n) {
if (r != t->nil) {
show_rbt_node(t, r->right, high + 7, n + 1);
int i = 0;
while (i != high) {
if (i % 7 == 0) {
if (i >= 7 * n)
printf("|");
else
printf(" ");
} else
printf(" ");
i++;
}
if (r->color == RED)
printf("|-<R>");
else printf("|-<B>");
printf("%2d-\n", r->key);
show_rbt_node(t, r->left, high + 7, n + 1);
} else {
int i = 0;
while (i != high) {
if (i % 7 == 0) {
if (i >= 7 * n)
printf("|");
else
printf(" ");
} else
printf(" ");
i++;
}
printf("|-NIL\n");
}
}
测试程序main.c,用随机数进行插入、删除测试,多次测试没有问题
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
/*
* File: main.c
* Author: weng
*
* Created on 2018年11月8日, 下午9:39
*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "rb_tree.h"
/*
*
*/
#define N_NODES 50
#define ARRAYSIZE 100001
int main(int argc, char** argv) {
int i, n = 0;
srand(time(0));
int array[ARRAYSIZE];
memset(array, -1, sizeof (array));
RBTree* t = create_rbtree();
for (i = 0; i < N_NODES; i++) {
int num = rand() % N_NODES;
insert_rbt_node(t, num);
/*
num = i;
insert_rbt_node(t, num);
*/
if (num != array[num]) {
printf("插入: %d \n", num);
array[num] = num;
n++;
} else {
printf("重复插入 %d\n", num);
}
}
printf("array: \n");
for (int i = 0; i < ARRAYSIZE; i++)
if (array[i] != -1)
printf("%d ", array[i]);
printf("\nhow many: %d\n", n);
printf("display: \n");
display_rbt(t);
display_rbt_prevorder(t);
display_rbt_postorder(t);
show_rbt(t);
for (i = 0; i < N_NODES; i++) {
int num = rand() % N_NODES;
remove_rbt_node(t, num);
/*
num = i;
remove_rbt_node(t, num);
*/
if (num == array[num]) {
printf("删除: %d \n", num);
array[num] = -1;
n--;
} else {
printf("重复删除或不存在 %d\n", num);
}
}
show_rbt(t);
printf("array: \n");
for (int i = 0; i < ARRAYSIZE; i++)
if (array[i] != -1)
printf("%d ", array[i]);
printf("\nhow many: %d\n", n);
printf("display: \n");
display_rbt(t);
display_rbt_prevorder(t);
display_rbt_postorder(t);
clear_rbtree(t);
free(t);
return (EXIT_SUCCESS);
}
这是随机插入20次并删除20次的整个过程
其他几次测试结果图