红黑树学习

              

红黑树:

 k v 方式

用在哪里:

1.hash

 强查找的过程:

 1.rbtree

 2.hash

 3.b/b+ tree

 4.链表

 红黑树:

 1.每个结点是红的或者是黑的

 2.根结点是黑的

 3.每个叶子结点是黑的

 4.如果一个结点是红的,则它的两个儿子是黑的

 5.对每个节点,从该节点到其子孙结点的所有路径上的包含路径上的黑结点相同

红黑树在插入任何一个结点之前,就是一颗红黑树

左旋:

右旋:

插入:

1.先找到合适的位置

2.先插入节点默认为红色,后面再进行调整

插入调整:

// 定义键类型的别名
typedef int KEY_TYPE;

// 定义红色和黑色的宏
#define RED 0
#define BLACK 1

// 定义红黑树节点结构的宏
#define RBTREE_ENTRY(name, type) \
    struct name                  \
    {                            \
        struct type *left;       \
        struct type *right;      \
                                 \
        struct type *parent;     \
                                 \
        unsigned char color;     \
    }

// 定义红黑树节点结构
typedef struct _rbtree_node
{
    KEY_TYPE key; // 节点键值
    void *value;  // 节点关联的值

#if 1
    struct rbtree_node *left;   // 左子节点指针
    struct rbtree_node *right;  // 右子节点指针
    struct rbtree_node *parent; // 父节点指针
    unsigned char color;        // 节点颜色
#else
    RBTREE_ENTRY(, rbtree_node) // 使用宏定义节点结构
    node;
#endif

} rbtree_node;

// 定义红黑树结构
typedef struct _rbtree
{
    rbtree_node *root; // 根节点指针
    rbtree_node *nil;  // 默认黑色空节点
} rbtree;

// 左旋操作
void rbtree_left_rotate(rbtree *tree, rbtree_node *x)
{
    // x的右子节点
    rbtree_node *y = x->right;

    // 1. 把y的左子节点变成x的右子节点
    x->right = y->left;
    if (y->left != tree->nil)
        y->left->parent = x;

    // 2. 把x变成y的左子节点
    y->parent = x->parent;
    if (x->parent == tree->nil)
        tree->root = y;
    else if (x == x->parent->left)
        x->parent->left = y;
    else
        x->parent->right = y;

    // 3. 把x变成y的左子节点
    y->left = x;
    x->parent = y;
}

// 右旋操作
void rbtree_right_rotate(rbtree *tree, rbtree_node *x)
{
    // x的左子节点
    rbtree_node *y = x->left;

    // 1. 把x的左子节点变成y的右子节点
    y->left = x->right;
    if (x->right != tree->nil)
        x->right->parent = y;

    // 2. 把y变成x的右子节点
    x->parent = y->parent;
    if (y->parent == tree->nil)
        tree->root = x;
    else if (y == y->parent->left)
        y->parent->left = x;
    else
        y->parent->right = x;

    // 3. 把y变成x的左子节点
    x->right = y;
    y->parent = x;
}

// 插入后修复红黑树性质
void rbtree_insert_fixup(rbtree *tree, rbtree_node *z)
{
    // 当z的父节点为红色时,需要修复红黑树性质
    while (z->parent->color == RED)
    {
        // 判断父节点是祖父节点的左子节点还是右子节点
        if (z->parent == z->parent->parent->left)
        {
            // 叔父节点
            rbtree_node *y = z->parent->right;
            if (y->color == RED)
            {
                // 情况1:父节点和叔父节点都是红色
                z->parent->color = BLACK;
                y->color = BLACK;
                z->parent->parent->color = RED;
                // 继续对祖父节点进行修复
                z = z->parent->parent;
            }
            else
            {
                // 情况2:父节点是红色,叔父节点是黑色
                if (z == z->parent->right)
                {
                    z = z->parent;
                    rbtree_right_rotate(tree, z);
                }

                // 情况3:父节点是红色,叔父节点是黑色
                if (z == z->parent->left)
                {
                    z->parent->color = BLACK;
                    z->parent->parent->color = RED;
                    rbtree_right_rotate(tree, z->parent->parent);
                }
            }
        }
        else
        {
            // 对称处理右子树的情况
        }
    }
}

// 插入节点到红黑树
void rbtree_insert(rbtree *t, rbtree_node *z)
{
    // 寻找插入位置
    rbtree_node *x = t->root;
    rbtree_node *y = t->nil;
    while (x != t->nil)
    {
        y = x;
        if (z->key < x->key)
        {
            x = x->left;
        }
        else if (z->key > x->key)
        {
            x = x->right;
        }
        else
        {
            // 如果键值已存在,则不插入
            return;
        }
    }

    // 将z插入到y的适当位置
    if (y->key >= z->key)
    {
        y->left = z;
    }
    else
    {
        y->right = z;
    }
    z->parent = y;
    z->left = t->nil;
    z->right = t->nil;
    z->color = RED;

    // 插入后修复红黑树性质
    rbtree_insert_fixup(t, z);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值