当前位置: 首页 > article >正文

红黑树学习

              

红黑树:

 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);
}


http://www.kler.cn/news/335603.html

相关文章:

  • 自然语言处理问答系统
  • windows下安装cmake+opencv(QT+MinGW版本)
  • 嵌入式硬件设计中EDA布局与布线实现
  • 微服务Sleuth解析部署使用全流程
  • OpenAI预计明年将推出“代理”系统
  • 一张图片生成数字人的3D发型:技术创新与应用前景
  • 【Python】Marmir 使用指南:Python 驱动的电子表格生成器
  • 佑航科技Pre-A+轮融资成功:加速车载超声波芯片研发与量产
  • 因浏览器未发送Referer HTTP头导致Django项目CSRF验证失败的原因
  • JavaScript中的(this)指向问题(如何正确判断this,箭头函数的this是什么)
  • 在 window 系统下安装 Ubuntu (虚拟机)
  • Maven的生命周期与依赖作用域介绍
  • Spring Data JPA
  • 大数据新视界 --大数据大厂之深度优化 Alluxio 分层架构:提升大数据缓存效率的全方位解析
  • 调试意义、步骤及方式
  • FreeRTOS列表与列表项
  • VRRP协议个人理解+报文示例+典型配置-RFC2338/RFC3768/RFC5798/RFC9568
  • 速盾:如何判断高防服务器的防御是否真实?
  • 计算机网络思维导图
  • 人工智能专业就业方向与前景