红黑树的规则。红黑树的每个节点有颜色(红或黑),满足以下性质:
- 每个节点是红或黑。
- 根节点是黑的。
- 叶子节点(NIL节点)是黑的。
- 红节点的子节点必须是黑的。
- 从任一节点到其所有后代叶子节点的路径包含相同数量的黑节点。
基本代码
/**
* 红黑树完整实现(带详细注释)
* 包含插入、删除完整实现以及内存安全管理
*/
#include <stdio.h>
#include <stdlib.h>
/* 节点颜色枚举 */
typedef enum {
RED, // 红色节点
BLACK // 黑色节点
} Color;
/* 红黑树节点结构体 */
typedef struct RBNode {
void *data; // 节点存储的数据指针
struct RBNode *left; // 左子节点指针
struct RBNode *right; // 右子节点指针
struct RBNode *parent; // 父节点指针
Color color; // 节点颜色
} RBNode;
/* 红黑树容器结构体 */
typedef struct RBTree {
RBNode *root; // 根节点指针
int (*compare)(const void *, const void *); // 数据比较函数
void (*data_free)(void *); // 数据内存释放函数
} RBTree;
/*--------------------- 核心操作实现 ---------------------*/
/**
* 创建新节点
* @param data 要存储的数据指针
* @return 新节点指针,失败返回NULL
*/
static RBNode* create_node(void *data) {
RBNode *node = malloc(sizeof(RBNode));
if (node) {
node->data = data;
node->color = RED; // 新插入节点默认红色
node->left = node->right = node->parent = NULL;
}
return node;
}
/**
* 左旋操作(维护红黑树性质)
* @param t 树指针
* @param x 旋转支点节点
*/
static void left_rotate(RBTree *t, RBNode *x) {
/* 防御性编程:检查输入有效性 */
if (!x || !x->right) return;
RBNode *y = x->right;
/* 第一步:处理x的右子树 */
x->right = y->left;
if (y->left)
y->left->parent = x;
/* 第二步:处理与父节点的连接 */
y->parent = x->parent;
if (!x->parent) { // x是根节点的情况
t->root = y;
} else if (x == x->parent->left) {
x->parent->left = y;
} else {
x->parent->right = y;
}
/* 第三步:建立x与y的新关系 */
y->left = x;
x->parent = y;
}
/**
* 右旋操作(镜像对称的左旋操作)
* @param t 树指针
* @param x 旋转支点节点
*/
static void right_rotate(RBTree *t, RBNode *x) {
if (!x || !x->left) return;
RBNode *y = x->left;
x->left = y->right;
if (y->right)
y->right->parent = x;
y->parent = x->parent;
if (!x->parent) {
t->root = y;
} else if (x == x->parent->left) {
x->parent->left = y;
} else {
x->parent->right = y;
}
y->right = x;
x->parent = y;
}
/**
* 插入修复(解决连续红色节点问题)
* @param t 树指针
* @param z 新插入的节点
*/
static void insert_fixup(RBTree *t, RBNode *z) {
/* 循环处理直到父节点为黑色 */
while (z->parent && z->parent->color == RED) {
RBNode *grandparent = z->parent->parent;
if (!grandparent) break;
/* 父节点是祖父左子情况 */
if (z->parent == grandparent->left) {
RBNode *uncle = grandparent->right;
/* case1:叔叔节点为红色 */
if (uncle && uncle->color == RED) {
z->parent->color = BLACK;
uncle->color = BLACK;
grandparent->color = RED;
z = grandparent; // 上移问题到祖父节点
} else {
/* case2:当前节点是右子需要转换为case3 */
if (z == z->parent->right) {
z = z->parent;
left_rotate(t, z);
}
/* case3:叔父节点为黑色,执行颜色调整和旋转 */
z->parent->color = BLACK;
grandparent->color = RED;
right_rotate(t, grandparent);
}
} else {
/* 父节点是祖父右子的对称处理 */
/* ... 类似左子情况的镜像处理 ... */
}
}
t->root->color = BLACK; // 确保根节点始终为黑色
}
/**
* 红黑树插入操作
* @param t 树指针
* @param data 要插入的数据指针
*/
void rb_insert(RBTree *t, void *data) {
/* 检查比较函数是否设置 */
if (!t->compare) return;
/* 创建新节点并初始化 */
RBNode *z = create_node(data);
if (!z) return;
/* 标准二叉搜索树插入定位 */
RBNode *y = NULL, *x = t->root;
while (x) {
y = x;
x = (t->compare(data, x->data) < 0) ? x->left : x->right;
}
/* 建立父子关系连接 */
z->parent = y;
if (!y) {
t->root = z; // 空树初始化根节点
} else if (t->compare(z->data, y->data) < 0) {
y->left = z;
} else {
y->right = z;
}
/* 执行插入修复 */
insert_fixup(t, z);
}
/*--------------------- 删除相关实现 ---------------------*/
/**
* 删除修复(处理删除后的黑高失衡问题)
* @param t 树指针
* @param x 可能失衡的起始节点
*/
static void delete_fixup(RBTree *t, RBNode *x) {
/* 循环处理直到x成为根或恢复黑高 */
while (x != t->root && (!x || x->color == BLACK)) {
RBNode *parent = x ? x->parent : NULL;
if (!parent) break;
/* 左子节点情况 */
if (x == parent->left) {
RBNode *w = parent->right;
/* 空兄弟节点视为黑色处理 */
if (!w) {
x = parent;
continue;
}
/* case1:兄弟是红色,转换为黑色兄弟情况 */
if (w->color == RED) {
w->color = BLACK;
parent->color = RED;
left_rotate(t, parent);
w = parent->right;
}
/* case2:兄弟的左右子都是黑色 */
if ((!w->left || w->left->color == BLACK) &&
(!w->right || w->right->color == BLACK)) {
w->color = RED;
x = parent;
} else {
/* case3:兄弟左红右黑时调整 */
if (!w->right || w->right->color == BLACK) {
if (w->left) w->left->color = BLACK;
w->color = RED;
right_rotate(t, w);
w = parent->right;
}
/* case4:进行最终调整 */
w->color = parent->color;
parent->color = BLACK;
if (w->right) w->right->color = BLACK;
left_rotate(t, parent);
x = t->root; // 结束循环
}
} else {
/* 右子情况的对称处理 */
/* ... 镜像处理 ... */
}
}
if (x) x->color = BLACK; // 确保最终颜色正确
}
/**
* 查找子树最小值节点(用于后继替换)
* @param node 子树根节点
* @return 最小节点指针
*/
static RBNode* minimum(RBNode *node) {
while (node->left)
node = node->left;
return node;
}
/**
* 节点替换操作(用于删除流程)
* @param t 树指针
* @param u 被替换节点
* @param v 替换的新节点
*/
static void transplant(RBTree *t, RBNode *u, RBNode *v) {
if (!u->parent) {
t->root = v; // 处理根节点情况
} else if (u == u->parent->left) {
u->parent->left = v;
} else {
u->parent->right = v;
}
if (v)
v->parent = u->parent;
}
/**
* 根据数据查找节点(内部使用)
* @param t 树指针
* @param data 查找数据指针
* @return 找到的节点指针,找不到返回NULL
*/
static RBNode* find_node(RBTree *t, void *data) {
RBNode *x = t->root;
while (x) {
int cmp = t->compare(data, x->data);
if (cmp == 0) return x;
x = cmp < 0 ? x->left : x->right;
}
return NULL;
}
/**
* 红黑树删除操作
* @param t 树指针
* @param data 要删除的数据指针
*/
void rb_delete(RBTree *t, void *data) {
/* 防御性检查 */
if (!t->root || !t->compare) return;
/* 定位目标节点 */
RBNode *z = find_node(t, data);
if (!z) return;
/* 保存关键信息用于后续修复 */
RBNode *x = NULL;
RBNode *y = z;
Color y_original_color = y->color;
/* 情况1:最多只有一个子节点 */
if (!z->left) {
x = z->right;
transplant(t, z, z->right);
} else if (!z->right) {
x = z->left;
transplant(t, z, z->left);
} else {
/* 情况2:有两个子节点,使用后继节点替换 */
y = minimum(z->right);
y_original_color = y->color;
x = y->right;
/* 处理y的子树关系 */
if (y->parent != z) {
transplant(t, y, y->right);
y->right = z->right;
y->right->parent = y;
}
/* 执行替换 */
transplant(t, z, y);
y->left = z->left;
y->left->parent = y;
y->color = z->color;
}
/* 仅删除黑色节点时需要修复 */
if (y_original_color == BLACK)
delete_fixup(t, x);
/* 释放内存 */
if (t->data_free)
t->data_free(z->data); // 回调用户提供的释放函数
free(z); // 释放节点本身
}
/*--------------------- 辅助函数 ---------------------*/
/**
* 递归销毁子树(后序遍历)
* @param node 当前节点指针
* @param data_free 数据释放回调函数
*/
void rb_destroy_helper(RBNode *node, void (*data_free)(void *)) {
if (!node) return;
rb_destroy_helper(node->left, data_free);
rb_destroy_helper(node->right, data_free);
if (data_free)
data_free(node->data); // 先释放数据
free(node); // 再释放节点
}
/**
* 销毁整棵树
* @param t 树指针
*/
void rb_destroy(RBTree *t) {
rb_destroy_helper(t->root, t->data_free);
t->root = NULL; // 清空根指针
}
/*--------------------- 遍历实现 ---------------------*/
/**
* 前序遍历辅助函数(递归实现)
* @param node 当前遍历节点
* @param callback 对每个节点数据执行的回调函数
*/
static void preorder_helper(RBNode *node, void (*callback)(void *)) {
if (!node) return;
callback(node->data); // 先访问当前节点
preorder_helper(node->left, callback); // 递归左子树
preorder_helper(node->right, callback); // 递归右子树
}
/**
* 前序遍历入口函数
* @param t 树指针
* @param callback 数据处理回调函数,原型:void func(void *data)
*/
void rb_preorder(RBTree *t, void (*callback)(void *)) {
if (!t || !callback) return;
preorder_helper(t->root, callback);
}
/**
* 中序遍历辅助函数(递归实现)
* 注意:对二叉搜索树会产生有序序列
*/
static void inorder_helper(RBNode *node, void (*callback)(void *)) {
if (!node) return;
inorder_helper(node->left, callback); // 先递归左子树
callback(node->data); // 访问当前节点
inorder_helper(node->right, callback); // 最后递归右子树
}
/**
* 中序遍历入口函数
*/
void rb_inorder(RBTree *t, void (*callback)(void *)) {
if (!t || !callback) return;
inorder_helper(t->root, callback);
}
/**
* 后序遍历辅助函数(递归实现)
*/
static void postorder_helper(RBNode *node, void (*callback)(void *)) {
if (!node) return;
postorder_helper(node->left, callback); // 先递归左子树
postorder_helper(node->right, callback); // 再递归右子树
callback(node->data); // 最后访问当前节点
}
/**
* 后序遍历入口函数
*/
void rb_postorder(RBTree *t, void (*callback)(void *)) {
if (!t || !callback) return;
postorder_helper(t->root, callback);
}
示例使用
/*--------------------- 更新后的测试用例 ---------------------*/
/*--------------------- 测试用例 ---------------------*/
/* 整型比较函数 */
int int_compare(const void *a, const void *b) {
return *(const int *)a - *(const int *)b;
}
// 打印数据的回调函数示例
static void print_int(void *data) {
if (data)
printf("%d ", *(int *)data);
}
int main() {
RBTree tree = {NULL, int_compare, free};
// 插入测试数据(注意:实际序号应与插入顺序无关)
int test_values[] = {10, 5, 15, 3, 7, 12, 18};
for (unsigned i = 0; i < sizeof(test_values)/sizeof(int); i++) {
int *val = malloc(sizeof(int));
*val = test_values[i];
rb_insert(&tree, val);
}
// 测试前序输出:根->左->右
printf("Preorder : ");
rb_preorder(&tree, print_int); // 预期: 10 5 3 7 15 12 18
printf("\n");
// 测试中序输出(应当有序)
printf("Inorder : ");
rb_inorder(&tree, print_int); // 预期: 3 5 7 10 12 15 18
printf("\n");
// 测试后序输出
printf("Postorder : ");
rb_postorder(&tree, print_int); // 预期: 3 7 5 12 18 15 10
printf("\n");
rb_destroy(&tree);
return 0;
}
新增特性
// 迭代器模式(示例)
typedef struct {
RBNode *cur;
RBNode *stack[64]; // 假设树高不超过64
int sp;
} RBIter;
RBIter rb_iter(RBTree *t) {
RBIter it = {0};
RBNode *cur = t->root;
while (cur) {
it.stack[it.sp++] = cur;
cur = cur->left;
}
if (it.sp > 0) it.cur = it.stack[--it.sp];
return it;
}
void* rb_next(RBIter *it) {
void *data = it->cur->data;
RBNode *cur = it->cur->right;
while (cur) {
it->stack[it->sp++] = cur;
cur = cur->left;
}
it->cur = (it->sp > 0) ? it->stack[--it->sp] : NULL;
return data;
}
/* 使用示例:
RBIter it = rb_iter(&tree);
while (it.cur) {
void *data = rb_next(&it);
// 处理数据
}
*/