红黑树纯c语言实现--继上一篇单黑色节点删除

一下是红黑树增删查,包含了一个完整的demo。

1. 由于插入操作比较简单,就不讲了直接上代码:

/**
 * @brief Left rotate.
 *   step:
 *      1. right child becomes the parent node, if current node`s parrent is null,
 *          the right node becomes root node.
 *      2. right child`s left child becomes current node`s right node.
 *      3. current node becomes right child`s left child.
 *      current node = previous parent node.
 *  eg:left node a.
 *           a                                c   
 *         /   \     left rotate            /   \
 *        b     c   ===============>>      a     g  
 *      /   \   / \                       / \
 *     d     e  f  g                     b   f
 *                                      / \
 *                                     d   e
 *  @return rd_node_t* 
 *                                    
 * @anchor cj
 */
void left_rotate(rd_node_t **root, rd_node_t *cur_node)
{
    rd_node_t *right_node = cur_node->right;

    /* step 1 */
    right_node->parent = cur_node->parent;
    if (!cur_node->parent) {
        /* current node is root. */
        *root =  right_node;
    } else if (cur_node == cur_node->parent->left) {
        /* if current node is in left tree. */
        cur_node->parent->left = right_node;
    } else {
        /* current node is right tree. */
        cur_node->parent->right = right_node;
    }

    /* step 2 */
    cur_node->right = right_node->left;
    if (right_node->left) {
        right_node->left->parent = cur_node;
    }

    /* step 3 */
    right_node->left = cur_node;
    cur_node->parent = right_node;
}



/**
 * @brief right rotate.
 *  step:
 *      1. left child becomes the parent node.if current node`s parrent is null,
 *          the left node becomes root node.
 *      2. left child`s right child becomes current node`s right node.
 *      3. current node becomes right child`s left child.
 *      current node = previous parent node.
 *  eg:right node a.
 *           a                                b   
 *         /   \     right rotate           /   \
 *        b     c   ===============>>      d     a  
 *      /   \   / \                             /  \
 *     d     e  f  g                           e    c
 *                                                 /  \
 *                                                f    g
 *  @return rd_node_t* 
 *                                    
 * @anchor cj
 */

void right_rotate(rd_node_t **root, rd_node_t *cur_node)
{
    rd_node_t *left_node = cur_node->left;
    struct test_info *info = NULL;

    /* step 1 */
    left_node->parent = cur_node->parent;
    if (!cur_node->parent) {
        /* root node. */
        *root = left_node;
    } else if (cur_node == cur_node->parent->left) {
        /* current node is left tree. */
        cur_node->parent->left = left_node;
    } else {
        /* current node is right tree. */
        cur_node->parent->right = left_node;
    }

    /* step 2. */
    cur_node->left = left_node->right;
    if (left_node->right) {
        left_node->right->parent = cur_node;
    }

    /* step 3. */
    cur_node->parent = left_node;
    left_node->right = cur_node;
}

/**
 * @brief 红黑树性质
 * 1. 每个节点要么是红色,要么是黑色。
 * 2. 根节点是黑色。
 * 3. 每个叶子节点(NIL节点)是黑色。----其实就是空指针叶子
 * 4. 如果一个节点是红色,那么它的两个子节点都是黑色。 ----- 插入一个节点要默认成红色原因,NIL节点是黑色的。
 * 5. 对于每个节点,从该节点到其所有后代叶子节点的简单路径上,均包含相同数目的黑色节点。
 * 
 */

/**
 * @brief fix red black tree 
 *  step:
 *  插入修正:
 *    当向红黑树中插入一个节点时,会破坏红黑树的平衡性质。为了修正这种破坏,需要进行以下操作:
 *
 *    a) 如果插入的是根节点,直接将其染成黑色。
 *    b) 如果插入的节点的父节点是黑色的,不需要做任何修正。
 *    c) 如果插入的节点的父节点是红色的,需要进行下面的修正操作:
 *      case 1. 当前节点的父节点是红色,且当前节点的祖父节点的另一个子节点(叔叔节点)也是红色
 *         (01)将“父节点”设为黑色。(02)将“叔叔节点”设为黑色。(03)将“祖父节点”设为“红色” (04)将“祖节点”设为“当前节点”(红色节点);即,之后继续对“当前节点”进行操作.    
 *      case 2. 父亲节点是左子树,当前节点的父节点是红色,叔叔节点是黑色,且当前节点是其父节点的右孩子
 *          (01)将“父节点”作为“新的当前节点”  (02)以“新的当前节点”为支点进行左旋。
 *      case 3. 父亲节点是左子树,当前节点的父节点是红色,叔叔节点是黑色,且当前节点是其父节点的左孩子
 *          (01)将“父节点”设为“黑色 (02)将“祖父节点”设为“红色”。(03)以“祖父节点”为支点进行右旋。
 *      case 4. 父亲节点是右子树,叔叔节点为黑色或者不存在,当前节点是父节点的左子节点,将设置当前节点为父节点,并以更新后的节点为支点进行右旋。
 *      case 5. 父亲节点是右子树,叔叔节点为黑色或者不存在,当前节点是父节点的右子节点,将当前节点的父节点染黑,祖父节点染红,设置当前节点为祖父节点,并以更新后的当前节点为支点进行左旋。
 * @author cj.2023-12-28
 * 
 * @return NULL
 */
void rd_fix_insert(rd_node_t **root, rd_node_t *cur_node)
{
    rd_node_t *uncle;

    /* 当前是根节点,直接染黑;如果父节点是红色,需要调整;由于根节点始终是黑色的,所以如果父节点是根节点时就不需要遍历调整了 */
    while (cur_node && cur_node->parent && cur_node->parent->parent && (cur_node->parent->color == RD_RED)) {
        if (cur_node->parent->parent->left == cur_node->parent) { /* 父节点是左子树,叔叔节点是右子树 */
            uncle = cur_node->parent->parent->right;
        } else { /* 父节点是右子树,叔叔节点是左子树 */
            uncle = cur_node->parent->parent->left;
        }

        /* 如果叔叔节点存在,则查看叔叔节点是否为红色,如果为红色,则叔叔节点和父亲节点染黑,祖父节点染红,并将当前节点置为祖父节点继续判断 */
        if (uncle && uncle->color == RD_RED) {
            uncle->color = RD_BLACK;
            cur_node->parent->color = RD_BLACK;
            cur_node->parent->parent->color = RD_RED;
            cur_node = cur_node->parent->parent;
            continue;
        } else {
            /* 如果父亲节点是左子树 */
            if (cur_node->parent->parent->left == cur_node->parent) {
                /* 如果叔叔节点不存在或者是黑色,且插入节点为左子节点,则将父节点染黑,祖父节点染红,并以祖父节点为支点进行右旋 */
                if (cur_node->parent->left == cur_node) {
                    cur_node->parent->color = RD_BLACK;
                    cur_node->parent->parent->color = RD_RED;
                    cur_node = cur_node->parent->parent;
                    right_rotate(root, cur_node);
                } else {
                    /* 如果插入节点是右子树,并以父节作为当前节点,以父节点为支点左旋 */
                    cur_node = cur_node->parent;
                    left_rotate(root, cur_node);
                }
            } else { /* 如果父亲节点是右子树 */
                /* 如果叔叔节点不存在或者是黑色,且插入节点为右子节点,则将父节点染黑,祖父节点染红,并以祖父节点为支点进行右旋 */
                if (cur_node->parent->right ==
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值