为什么红黑树如此受欢迎
创始人
2024-05-31 20:35:43
0

平衡二叉查找树有很多,但是我们一提到平衡二叉查找树,常提及的就是红黑树,它的“出镜率”甚至要高于平衡二叉查找树。

红黑树是一种相对平衡的二叉查找树,不符合严格意义上平衡二叉查找树的定义。

目录

红黑树的插入

 红黑树的验证


红黑树的性质

  • 每个结点不是红色就是黑色
  • 根节点是黑色的 
  • 任何上下相邻的节点不能同时为红色 如果一个节点是红色的,则它的两个孩子结点是黑色的 
  •  对于每个结点,从该结点到其所有后代叶结点的所有路径,都包含相同数目的黑色结点 
  • 每个叶子结点都是黑色的空节点,也就是说,叶子节点不存储数据。

满足上面的性质,红黑树就能保证:其最长路径中节点个数不会超过最短路径节点个数的两倍。

红黑树的性能分析

假设每条路径上的黑节点是N,最短的路径全是黑节点,最长的路径节点一个黑节点一个红节点相间 ,N<=任意路径长度<=2N。

平衡二叉查找树的提出是为了解决二叉查找树因为动态更新导致的性能退化问题。因此,“平衡”可以等价为性能不退化,“近似平衡”就等价为性能退化不太严重。二叉查找树的很多操作的时间复杂度与树的高度成正比。一颗极其平衡的二叉树(满二叉树或完全二叉树)的高度大约是log n,如果要证明红黑树是近似平衡的,只需要证明红黑树的高度近似于log n(比如同一量级)。

证明:

 红黑树的最长路径不会超过2log n,也就是说,红黑树的高度不会超过2log n。红黑树只比高度平衡的AVL树高了一倍,因此损失的性能并不多。而相对于AVL树,红黑树维护成本更低,因此,性能并不比AVL树差。

所以为什么红黑树如此受欢迎呢? 

AVL树是一种高度平衡的二叉树,查找数据的效率非常高,但是,AVL树为了维持这种高度的平衡,需要付出更多的代价。为了维持平衡性,每次插入、删除数据都要对树中节点的分布做调整,操作复杂、耗时。
红黑树只做到了近似平衡,并没有做到严格定义上的平衡,因此,维护平衡性的成本比AVL树要低,但性能又损失不大。对于工程应用,我们更倾向于维护成本和性能相对折中的红黑树。更加重要的一点是,大部分编程语言提供了封装了红黑树实现的类,我们直接拿来用即可,不需要从零开始实现,大大节省了开发时间。红黑树是一种近似平衡的二叉查找树。 它是为了解决二叉查找树动态数据更新导致的性能退化问题而创造的。红黑树的高度近似于logn,插入、删除和查找操作的时间复杂度都是O(logn)。
 

红黑树节点的定义 

   // 节点的颜色
    enum Color { RED, BLACK };


    // 红黑树节点的定义
    template
    struct RBTreeNode
    {
        RBTreeNode(const T& data = T(),Color color = RED)
            : _pLeft(nullptr), _pRight(nullptr), _pParent(nullptr)
            , _data(data), _color(color)
        {}
        RBTreeNode* _pLeft;   // 节点的左孩子
        RBTreeNode* _pRight;  // 节点的右孩子
        RBTreeNode* _pParent; // 节点的双亲
        T_data;            // 节点的值域
        Color _color;               // 节点的颜色
    };

在插入节点时,我们将节点的默认颜色给成红色的,因为每条路径上黑色节点相同,如果将节点给成黑色的,就会影响每一条路径,将新节点给成红色如果不符合规则,只需要调整这一条或者相邻路径,将新节点给成红色比将新节点给成黑色代价要小得多。

红黑树的插入

红黑树是在二叉搜索树的基础上加上其平衡限制条件,因此红黑树的插入可分为两步:

1. 按照二叉搜索的树规则插入新节点

2.检测新节点插入后,红黑树的性质是否造到破坏

因为新节点的默认颜色是红色,如果其双亲节点的颜色是黑色,没有违反红黑树任何性质,则不需要调整;但当新插入节点的双亲节点颜色为红色时,就违反了红黑树的性质,不能有连在一起的红色节点,此时需要对红黑树分情况来讨论:

cur为当前节点,p为父节点,g为祖父节点,u为叔叔节点

cur节点不一定是新增节点,有可能是调整之后指向的节点。

情况一: cur为红,p为红,g为黑,u存在且为红

解决方式:将p,u改为黑,g改为红,然后把g当成cur,继续向上调整。

情况二: cur为红,p为红,g为黑,u不存在/u存在且为黑 

u的情况有两种
1.如果u节点不存在,则cur一定是新插入节点,因为如果cur不是新插入节点,则cur和p一定有一个节点的颜色是黑色,就不满足性质∶每条路径黑色节点个数相同。
2.如果u节点存在,则其一定是黑色的,那么cur节点原来的颜色一定是黑色的,现在看到其是红色的原因是因为cur的子树在调整的过程中将cur节点的颜色由黑色改成红色。

解决方式:p为g的左孩子,cur为p的左孩子,则进行右单旋转;相反, p为g的右孩子,cur为p的右孩子,则进行左单旋转 p、g变色--p变黑,g变红 

情况三: cur为红,p为红,g为黑,u不存在/u存在且为黑

p为g的左孩子,cur为p的右孩子,则针对p做左单旋转;相反, p为g的右孩子,cur为p的左孩子,则针对p做右单旋转,则转换成了情况2

代码实现:

bool Insert(const T& data){if (_root == nullptr){_root = new Node(data);return true;}Node* parent = nullptr;Node* cur = _root;while (cur){if (data > cur->_data){parent = cur;cur = cur->_right}else if (data < >> cur->_data){parent = cur;cur = cur->_left}else {return false;}}//插入节点cur = new Node(data);cur->_col(RED);if (parent->data < data){parent->_right = cur;cur->_parent = parent;}else{parent->_left = cur;cur->_parent = parent;}//控制平衡while (parent && parent->_col == RED){Node* grandfather = parent->_parent;if (parent == grandfather->_left){Node* uncle = parent->_right;//1.uncle存在且为红if (uncle && uncle->_col == RED){//变色+继续向上处理parent->_col = uncle->_col = BLACK;grandfather->_col = RED;cur = grandfather;parent = cur->_parent;}else//2.uncle不存在/uncle存在且为黑{//        g//     p//  c//        g//     p//        cif (cur == parent->_left){//右旋RotateR(grandfather);parent->_col = BLACK;grandfather->_col = RED;}if (cur == parent->_right){//先左旋再右旋RotateL(parent);RotateR(grandfather);parent->_col = BLACK;grandfather->_col = RED;}break;}}else // parent == grandfather->_right{Node* uncle = grandfather->_left;if (uncle && uncle->_col == RED){// 变色+继续向上处理parent->_col = uncle->_col = BLACK;grandfather->_col = RED;cur = grandfather;parent = cur->_parent;}else // 2 + 3、uncle不存在/ 存在且为黑{//  g    //     p//        c//  g//     p//  cif (cur == parent->_right){RotateL(grandfather);parent->_col = BLACK;grandfather->_col = RED;}else{RotateR(parent);RotateL(grandfather);cur->_col = BLACK;grandfather->_col = RED;}break;}}}_root->_col = BLACK;return true;}

 红黑树的验证

红黑树的检测分为两步:

1. 检测其是否满足二叉搜索树(中序遍历是否为有序序列)

2. 检测其是否满足红黑树的性质

bool IsBalance(){if (_root && _root->_col == RED){cout << "根节点不是黑色" << endl;return false;}// 最左路径黑色节点数量做基准值int banchmark = 0;Node* left = _root;while (left){if (left->_col == BLACK)++banchmark;left = left->_left;}int blackNum = 0;return _IsBalance(_root, banchmark, blackNum);}bool _IsBalance(Node* root, int banchmark, int blackNum){if (root == nullptr){if (banchmark != blackNum){cout << "存在路径黑色节点的数量不相等" << endl;return false;}return true;}if (root->_col == RED && root->_parent->_col == RED){cout << "出现连续红色节点" << endl;return false;}if (root->_col == BLACK){++blackNum;}return _IsBalance(root->_left, banchmark, blackNum)&& _IsBalance(root->_right, banchmark, blackNum);}

相关内容

热门资讯

多城联动!辽宁消防“安全盛宴”...   5月8日,辽宁省消防救援总队以创意形式和贴心服务,在鞍山、抚顺、丹东、锦州、营口等地同步开展多元...
大美江湖,天下岳阳   千年巴陵,江湖旧梦;一座岳阳,四水归心。  当千年岳阳楼的飞檐在XR空间里再度挑起月色,当洞庭湖...
王帅红在全市开发区工作推进会上... 5月9日,全市开发区工作推进会召开。会议深入学习贯彻习近平总书记关于开发区工作的重要指示精神,认真贯...
林志玲深夜晒合照回忆与大S首次... 5月10日晚,林志玲晒合照,怀念第一次见到大S:第一次见到大S,是在一个冰淇淋店。当时还没有入行的我...
boc某行刚涨薪了? (转自:五道口江湖)近日,有多名山东、河北、河南地区boc行的网友分享,上个月涨薪了。其中山东地区的...
CPI环比由降转涨 部分工业行... 转自:衢州日报  4月份,全国居民消费价格指数(CPI)环比由上月下降0.4%转为上涨0.1%,扣除...
应急处置演练 转自:衢州日报  近日,柯城区衢化街道组织开展防汛防台应急处置演练。此次演练包括桌面推演和卫星电话、...
胡忠雄主持召开贵安新区党工委巡... 5月10日,省委常委、贵安新区党工委书记胡忠雄主持召开新区党工委巡视整改工作领导小组会议。他强调,要...
“夜游信安湖”入选省级精品航线 转自:衢州日报  本报讯 (通讯员 吴丽芬 戴晨涛) 近日,全省水路交旅融合品牌——“泛舟浙里”发布...
中原建业:1-4月合约销售35... 业绩快报5月9日,中原建业有限公司(股票代码:09982.HK,以下简称“中原建业”)发布2025年...
新华社评论员:守护历史记忆,共... 转自:北京日报客户端当地时间5月9日,俄罗斯莫斯科红场碧空澄澈、旗帜招展,纪念苏联伟大卫国战争胜利8...
2025年前4个月,我国货物贸... 海关总署日前发布数据显示,2025年前4个月,以人民币计,我国货物贸易进出口总值14.14万亿元,同...
南京鼓楼城管上门服务指导湖南路... 转自:扬子晚报扬子晚报网5月10日讯(通讯员 李亦军 记者 张可)近期,南京鼓楼城管大队湖管会中队联...
多出去玩能减少身体炎症 多接触大自然的人更健康与城市相比,自然环境中的景色、气味、声音更能促进身心健康。发表于美国《大脑行为...
头部投行美女转行瑜伽! (转自:五道口江湖)一名香港普拉提老师说:一年前的差不多这个時候我交还了Morgan Stanley...
中自科技携手天津大学、王成山院... 5月8日,在成都举办的“青城论道低碳能源共生发展”大会上,中自科技股份有限公司与天津大学、中国工程院...
鲁慕迅逝世,享年98岁 湖北省文联鲁慕迅同志治丧小组5月9日发布讣告,湖北省文联离休干部、省美术家协会原副主席、一级美术师鲁...
听·见|“被名言”借助网络泛滥... ——莫言说:“我不够成熟,不够圆滑,不够老练。没关系,我只不过是一个晚熟的人。”原来莫爷爷是我的同类...
曝光AL保险资管公司领导 (转自:五道口江湖)近日网传的一份文件,吐槽AL保险资管公司领导,对实习生不尊重,缺乏专业能力,人际...
成都蓉城客场4-0横扫梅州客家... 封面新闻记者 陈羽啸北京时间5月10日晚,2025赛季中超联赛第12轮在五华奥体中心展开争夺,成都蓉...