首页 > 其他分享 >【简易版tinySTL】 红黑树- 定义, 插入, 构建

【简易版tinySTL】 红黑树- 定义, 插入, 构建

时间:2024-06-30 21:57:51浏览次数:3  
标签:node 结点 parent father 简易版 son tinySTL 红黑树 left

文章目录

旋转

image-20240613095136796

对于一个平衡二叉搜索树,左子树高度为4,右子树高度为2,它们的高度差为2,破坏了平衡性(高度差<2才算平衡,因此需要调整二叉树使其平衡)

二叉树最基本的调整方式包括左旋、右旋:

左旋

  • 不平衡点没有左子树

image-20240613095515121

  • 不平衡点有左子树

image-20240613095615583

当结点5左旋时,由于有左子树3,会和结点6冲突,阻碍旋转,我们需要将"冲突的左孩变右孩",即将结点6连在被旋转点5的右孩子上

右旋

  • 不平衡点没有右子树

image-20240613095954955

  • 不平衡点有右子树

image-20240613100021786

当结点14右旋时,由于有右子树17,会和结点9冲突,阻碍旋转,我们需要将"冲突的右孩变左孩",即将结点9连在被旋转点14的左孩子上

左旋右旋代码实现

Node* rightRotate(Node* node)
{
    // node为失衡节点
    Node* l_son = node->left;

    // 不管是否会发生冲突,都把冲突的右孩变左孩
    node->left = l_son->right;
    // 右孩变左孩后,更新父节点(前提它不是空节点)
    if(node->left)
    {
        node->left->parent = node;
    }

    // 更新旋转中心的父节点指向
    l_son->parent = node->parent;
    // 如果当前节点(node)是根节点,则更新根节点为 l_son
    if(l_son->parent == nullptr)
    {
        root = l_son;
    }
    // 如果node是父结点的左子节点
    else if(node->parent->left == node)
    {
        node->parent->left = l_son;
    }
    else
    {
        // 如果node是父结点的右子节点
        node->parent->right = l_son;
    }

    // 把node结点接在l_son右边
    node->parent = l_son;
    l_son->right = node;

    return l_son;
}

Node* leftRotate(Node* node)
{
    Node* r_son = node->right;
    // 提前断掉右结点
    node->right = r_son->left;
    if(r_son->left)
    {
        node->right = r_son->left;
        r_son->left->parent = node;
    }

    r_son->parent = node->parent;
    if(r_son->parent == nullptr)
    {
        root = r_son;
    }
    else if(node->parent->left == node)
    {
        node->parent->left = r_son;
    }
    else
    {
        node->parent->right = r_son;
    }

    r_son->left = node;
    node->parent = r_son;

    return r_son;
}

红黑树的基本性质

空结点也是红黑树的叶子结点,也属于黑结点

  • 根叶黑:根和叶子结点默认为黑色
  • 不红红:不存在连续2个红色结点
  • 黑路同:任一结点到叶子结点的所有路径,黑结点的数量相同(包括空结点/叶子结点)

image-20240613100233691

红黑树的插入

要求:

  1. 默认插入的都是红色
  2. 插入情况讨论:
    • 插入的结点是根结点:直接变黑
    • 插入结点的叔叔结点是红色:叔父爷变色,当前指针指向爷爷结点,修复爷爷结点的红黑树性质
    • 插入结点的叔叔结点是黑色:先旋转(LL、RR、LR、RL),后变色

image-20240620191458222

image-20240620191519731

image-20240620192947162

红黑树的插入示例

假设我们要依次插入:17、18、23、34、27、15、9、6、8、5、25

我们每次插入之后,都要检查是否满足红黑树的性质

微信图片_20240620192221

红黑树修复代码实现

/*
		    O
		   /
		  O 
		 /
		O	<= target
*/
void insertFixup(Node* target) // target是当前插入的结点
{
    // 父结点存在,且出现红红
    while(target->parent && target->parent->color == Color::RED)
    {
        Node* father = target->parent;
        Node* g_father;
        if(father)
            g_father = father->parent;

        // 父是爷的左孩子
        if(g_father && g_father->left == father)
        {
            Node* uncle = g_father->right;
            // 如果叔结点存在,且颜色为红色
            if(uncle && uncle->color == Color::RED)
            {
                // 叔父爷变色
                uncle->color = Color::BLACK;
                father->color = Color::BLACK;
                g_father->color = Color::RED;
                // 将当前指针指向爷结点
                target = g_father;
            }
            // 叔结点不存在或者颜色为黑色(LL/LR)
            else
            {
                // LR
                if(target == g_father->left->right)
                {
                    // 先左旋,旋转函数的输入结点是失衡点
                    leftRotate(father);
                }
                // RR和LR后面的步骤都是一样的
                Node* t = rightRotate(g_father);
                // 变色
                t->color = Color::BLACK;
                t->right->color = Color::RED;
                t->left->color = Color::RED;
                return;
            }
        }

        if(g_father && g_father->right == father)
        {
            Node* uncle = g_father->left;
            if(uncle && uncle->color == Color::RED)
            {
                g_father->color = Color::RED;
                father->color = Color::BLACK;
                uncle->color = Color::BLACK;
                target = g_father;
            }
            else
            {
                // RL
                if(target == g_father->right->left)
                {
                    // !不是旋转父结点
                    rightRotate(father);
                }
                // LL和RL后续都一样
                Node* t = leftRotate(g_father);
                t->color = Color::BLACK;
                t->left->color = Color::RED;
                t->right->color = Color::RED;
                return;
            }
        }
        root->color = Color::BLACK;
    }
}

void insert(Key k, Value v)
{
    Node* node = new Node(k, v);
    Node* p = nullptr;
    Node* cur = root;
    if(this->size == 0)
    {
        root = node;
        size++;
        return;
    }
	// 找到插入点
    while(cur)
    {
        p = cur;
        if(k > cur->key)
        {
            cur = cur->right;
        }
        else if(k < cur->key)
        {
            cur = cur->left;
        }
        else
        {
            std::cout << "the key was in the tree" << std::endl;
            delete node;
            return;
        }
    }
    // 插入新结点
    size++;
    if(k > p->key)
    {
        p->right = node;
    }
    else
    {
        p->left = node;
    }

    node->parent = p;
    if(!p)
    {
        root = node;
    }
    // 修复红黑树
    insertFixup(node);
}

参考资料

红黑树 - 定义, 插入, 构建

红黑树 - 删除

标签:node,结点,parent,father,简易版,son,tinySTL,红黑树,left
From: https://blog.csdn.net/henghuizan2771/article/details/140087222

相关文章

  • 数据结构与算法-红黑树的java实现-构建红黑树
    红黑树红黑树是一种二分查找树,与普通的二分查找树不同的一点是,红黑树的每个节点都有一个颜色(color)属性。该属性的值要么是红色,要么是黑色。通过限制从根到叶子的任何简单路径上的节点颜色,红黑树确保没有比任何其他路径长两倍的路径,从而使树近似平衡。节点红黑树的节......
  • [C++][数据结构][红黑树]详细讲解
    目录1.红黑树的概念2.红黑树的性质3.红黑树节点的定义4.红黑树的结构5.红黑树的插入操作1.cur为红,p为红,g为黑,u存在且为红2.cur为红,p为红,g为黑,u不存在/u存在且为黑--单旋+变色3.cur为红,p为红,g为黑,u不存在/u存在且为黑--双旋+变色6.红黑树的迭代器1.begin()与end()2.o......
  • C++ -- 红黑树的基本操作
    目录摘要基本规则基本操作利用Graphviz库总结摘要红黑树是一种自平衡的二叉搜索树,它在插入和删除节点时,通过颜色和旋转操作保持树的平衡,确保插入、删除和查找的时间复杂度都是(O(logn))。红黑树的每个节点都有一个颜色属性,红色或黑色。通过一些规则,红黑树保持了相对......
  • Java基础:B树、B+树和红黑树的数据结构,三者区别
    B树(B-Tree)数据结构节点结构:每个节点包含多个键值和子节点指针。阶(Degree):B树的阶定义了每个节点的最小和最大键值数。对于阶为(m)的B树:每个节点最多有(m-1)个键值和(m)个子节点。每个节点(除了根节点)至少有(\lceilm/2\rceil-1)个键值和(\lceilm/......
  • 【python】用panda3d实现简易版《Minecraft》
    1.下載panda3d等等     panda3d是python的一个第三方库,在Windows的cmd下输入即可下載:pipinstallpanda3d     另外还用了 PIL,Pmw,ttkbootstrap這些第三方库,下載方式同上。。。2.方块模型     对于建模小白来说,blender有亿点难!! (资源放......
  • 红黑树/红黑树迭代器封装(C++)
        本篇将会较为全面的讲解有关红黑树的特点,插入操作,然后使用代码模拟实现红黑树,同时还会封装出红黑树的迭代器。    在STL库中的set和map都是使用红黑树封装的,在前文中我们讲解了AVL树,对于红黑树和AVL树来说,这两种树都是效率很高的搜索二叉树,但是......
  • 联系人管理系统(简易版)
    1、项目介绍    本项目以sqlite3为基本框架完成一个简易的手机联系人管理系统,用户可以根据自己需要进行添加联系人、删除联系人、更新联系人、查找联系人以及退出等。2、本项目涉及到的sqlite3API①sqlite3_open()函数用于打开一个SQLite数据库文件的函数,这个函......
  • 拿捏红黑树(C++)
    文章目录前言一、红黑树介绍二、插入操作三、验证红黑树四、红黑树与AVL性能比较与应用五、总体代码总结前言我们之前介绍了一种AVL的高阶数据结构,在本篇文章中,我们将会介绍一种与AVL旗鼓相当的数据结构–红黑树。我们并且会对它的部分接口进行模拟实现一、红黑树......
  • 红黑树-数据结构
    平衡二叉B树每个节点可以是红或者是黑红黑树不是高度平衡的,他的平衡是“通过自己的红黑规则实现的”红黑规则每个节点是红或者为黑根节点必须是黑色如果一个节点没有子节点或者是父节点,这个节点的相应的指针属性为nil,这些nil视为叶节点,每个叶节点nil是黑色的如果某个节......
  • 重学java 58.红黑树相关集合
    现在还来得及                ——24.6.3一、TreeSet1.概述:        Treeset是set的实现类2.特点:        a.对元素进行排序        b.无索引        c.不能存null        d.线程不安全    ......