基本数据结构--平衡二叉搜索树之红黑树示例代码

红黑树的规则。红黑树的每个节点有颜色(红或黑),满足以下性质:

  1. 每个节点是红或黑。
  2. 根节点是黑的。
  3. 叶子节点(NIL节点)是黑的。
  4. 红节点的子节点必须是黑的。
  5. 从任一节点到其所有后代叶子节点的路径包含相同数量的黑节点。

基本代码

/**
 * 红黑树完整实现(带详细注释)
 * 包含插入、删除完整实现以及内存安全管理 
 */
 
#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);
    // 处理数据 
}
*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

和风化雨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值