STL-红黑树源码实现

红黑树实现源码 关于红黑树的功能实现 立即下载

红黑树的介绍

它是一种特殊的二叉查找树,红黑树的每个节点上都有存储位表示节点的颜色,可以是红或者黑。

红黑树的特性

1.每个节点或者黑色或者红色

2.根节点是黑色

3.每个叶子节点是黑色

4.如果一个节点是红色,它的子节点必须是黑色的

5.从一个节点到该节点的子孙节点的所有路径上包含相同数目的黑节点

红黑树的操作

左旋

对x进行左旋,意味着“将X变为一个左节点”

右旋

平衡调节

新插入X,父节点P,G是P的父节点,S是G的另外一个子节点。

新节点x必须为叶节点,插入的节点必须为红色;

如果P是红色,必须调整红色,根据X的插入位置,有4种情况:

1:S为黑色且X为外侧插入,先对P,G左一次单旋转,在更改P,G颜色,重新满足红黑树的规则3:

2.S为黑且X为内侧插入,先对P,X做一次单旋转并更改G,X颜色,再将结果对G做一次单旋转,满足红黑树的规则

3.S为红色,且X为外侧插入,先对P和G做一次单旋转,并改变X的颜色,此时,如果GG(G的父节点)为黑色,符合规则;否则,进入情况4

 

或者

4.S为红色且X为外侧插入,先对P和G做一次单旋转,并改变X的颜色,如果G的父节点,仍然为红色,继续往上做,直到父子连续部位红的情况。

或者

 

红黑树的实现

节点的定义

struct _Node {
        _Nodeptr _Left, _Parent, _Right;
        _Ty _Value;
        _Redbl _color;
    };

节点的父节点,左右孩子节点

 

初始化

申请一个节点,赋值给_Nil, 并且左右子节点为0;并在构造一个节点_Head,并且设置为红色节点,父指针指向_Nil节点,左右子节点都指向自己。

_Head节点和红黑树的根节点的父节点,是相互指向。

_Nil用来表示null节点。

_Lmost,指向最左边的节点,_Rmost,指向最右边的节点,可以用来求最小和最大值。

void _Init() {
        _Nodeptr _Tmp = _Buynode(0, _Black);
        {
            _Lockit _Lk;
            if (_Nil == 0) {
                _Nil = _Tmp;
                _Tmp = 0;
                _Left(_Nil) = 0, _Right(_Nil) = 0;
            }
            ++_Nilerefs;
        }
        if (_Tmp != 0) {
            _Freenode(_Tmp);
        }
        _Head = _Buy(_Nil, _Red), _Size = 0;
        _Lmost() = _Head, _Rmost() = _Head;
    }

数据的插入

实现左旋

_Nodeptr _Y = _Right(_X);
        _Right(_X) = _Left(_Y);
        if (_Left(_Y) != _Nil) {
            _Parent(_Left(_Y)) = _X;
        }
        _Parent(_Y) = _Parent(_X);
        if (_X == _Root()) {
            _Root() = _Y;
        }
        else if (_X == _Left(_Parent(_X))) {
            _Left(_Parent(_X)) = _Y;
        }
        else {
            _Right(_Parent(_X)) = _Y;
        }
        _Left(_Y) = _X;
        _Parent(_X) = _Y;
    }

实现右旋

void _Rrotate(_Nodeptr _X) {
        _Nodeptr _Y = _Left(_X);
        _Left(_X) = _Right(_Y);
        if (_Right(_Y) != _Nil) {
            _Parent(_Right(_Y)) = _X;
        }
        _Parent(_Y) = _Parent(_X);
        if (_X == _Root())
            _Root() = _Y;
        else if (_X == _Right(_Parent(_X))) {
            _Right(_Parent(_X)) = _Y;
        }
        else {
            _Left(_Parent(_X)) = _Y;
        }
        _Right(_Y) = _X;
        _Parent(_X) = _Y;
    }

红黑树删除

红黑树的删除分为两种情况,情况1是有两个子的情况,情况2最多有一个子树的情况

 _Nodeptr _X;
        _Nodeptr _Y = (_P++)._Mynode();
        _Nodeptr _Z = _Y;

_Y:表示的是要删除的节点,_P表示的是临近_Y的大的节点

_Z:赋值为_Y

情况1:最多有一个子树的情况

  •    如果左子树或者右子树为空的情况   

if (_Left(_Y) == _Nil) {
            _X = _Right(_Y);
        }
        else if (_Right(_Y) == _Nil) {
            _X = _Left(_Y);
        }

 

把_X分别设置为右子树和左子树。

  • 然后把_X的父节点,设置为_Y的父节点即可;

      _Parent(_X) = _Parent(_Y);

  • 特殊情况判断,如果为root()节点

if (_Root() == _Z)
                _Root() = _X;

否则就设置_Z的左右子树

else if (_Left(_Parent(_Z)) == _Z) {
                _Left(_Parent(_Z)) = _X;
            }
            else {
                _Right(_Parent(_Z)) = _X;
            }

  • 判断是否为_Lmost  

if (_Lmost() != _Z) {
                ;
            }

如果_Z是_Lmost就把_Z的父节点,设置为_Lmost
            else if (_Right(_Z) == _Nil) {
                _Lmost() = _Parent(_Z);
            }
            else {
                _Lmost() = _Min(_X);
            }

_Rmost的判断是同样的。

情况2:有两个子树的情况


            _Y = _Min(_Right(_Y));
            _X = _Right(_Y);

去_Y的右子树的最小节点,然后把_X置为该节点的右数,_Z是要删除的节点。目的是把_Y这个节点,放到_Z的位置上去;接下来就是要调整,_Z,_Y的左右子树和父节点的指向。

  • 更新_Z的左右子树的父节点的指向为_Y

_Parent(_Left(_Z)) = _Y;

  • 更新_Y的左子树的指向为_Z的左子树的指向

 _Left(_Y) = _Left(_Z);

  • 如果恰好_Y==_Right(_Z)

if (_Y == _Right(_Z)) {
                _Parent(_X) = _Y;
            }

  • 否则

                    _Parent(_X) = _Parent(_Y);
                    _Left(_Parent(_Y)) = _X;
                    _Right(_Y) = _Right(_Z);
                    _Parent(_Right(_Z)) = _Y;

删除后平衡调整

如果删除的是黑色节点,才需要进行平衡调整。

分析左子树的情况:

while (_X != _Root() && _Color(_X) == _Black) {
                if (_X == _Left(_Parent(_X))) {

  • 获取_X节点的父节点的右子树

_Nodeptr _W = _Right(_Parent(_X));

  • 如果_W的颜色是红色

_Color(_W) = _Black;
                        _Color(_Parent(_X)) = _Red;
                        _Lrotate(_Parent(_X));
                        _W = _Right(_Parent(_X));

if (_Color(_Left(_W)) == _Black&&_Color(_Right(_W)==_Black) {
                        _Color(_W)=_Red;
                        _X=_Parent(_X);
                    }
                    else {
                        if (_Color(_Right(_W)) == _Black) {
                            _Color(_Left(_W))=_Black;
                            _Color(_W)=_Red;
                            _Rrotate(_W);
                            _W=_Right(_Parent(_X));
                        }
                        _Color(_W) = _Color(_Parent(_X));
                        _Color(_Parent(_X)) = _Black;
                        _Color(_Right(_W)) = _Black;
                        _Lrotate(_Parent(_X));
                        break;

                    }

Pyinstaller打包为可执行文件编码错误的问题 Pyinstaller打包为可执行文件编码错误的问题 写好的python程序在vscode上运行没有任何问题,将程序利用pyinstaller打包后,运行程序发生了错误。 错误代码 UnicodeDecodeError: ‘utf-8' codec can't decode byte 0xce in position 20-21:invalid cotinuation byte 网上找到的解决方案是: 1.在命令行中输入 chcp 65001 2.按正常方式进行封装 pyinstaller 阅读详情

相关推荐

SpringBoot 通过 JMS 集成 IBM MQ

IBM MQ 作为老牌的企业级消息中间件,虽然在当下云原生时代已不再是主流选择,但在金融、银行、保险等传统行业的核心业务系统中仍然占据着重要地位。这些行业对系统的稳定性、可靠性和事务一致性有着极高的要求,IBM MQ 正是在这些方面表现出色。尽管近年来 RabbitMQ、Apache Kafka 等新一代消息中间件在新兴项目中更受欢迎,但许多金融公司和大型企业仍在使用 IBM MQ 作为核心业务系统的消息传递基础设施。

小单的博客专栏 952

红黑树-带源码

红黑树是一种自平衡二叉查找树,通过红黑规则和旋转操作确保近似平衡,使基本操作时间复杂度稳定在O(logn)。文章详细介绍了红黑树的插入原理(三种情形)、删除原理(四种情形)以及其Java实现。插入时通过变色和旋转(LL/LR/RL/RR)修复红黑性质,删除操作更复杂但核心是维护黑高平衡。代码采用自顶向下插入策略,包含节点类、插入方法和旋转调整等关键部分。与AVL树相比,红黑树在插入删除性能上更优,广泛应用于集合结构和标准库实现。

道可道非常道 631

删除结点

对给定的单链表 L ,设计一个算法,删除 L 中值为 x 的结点的直接前驱结点。 1 由键盘输入值,换行表示输入结束,根据输入建立单链表。 2 输入链表中的一个元素值,从链表中删除这个元素的前驱结点。 3 对删除元素后的链表元素在屏幕上显示。 测试用例1 11 22 33 44 55 66 77↵ 44↵ 期待输出1 11 22 44 55 66 77↵ #include <iostre...

SChenlyx 1618

C++ 实现红黑树详解(内附源码)

一篇文章带你彻底学会手撕红黑树(内附源码)

2301_77754590的博客 1615

Claude Code 处理长任务 + Cursor 专注交互:双栈协作的 3 种分工场景与响应提速 35% 实测

揭示 Claude Code 与 Cursor 在 AI 编程中的本质分工:Claude Code 作为离线式架构师处理跨文件、带约束的长链路重构(如单体拆微服务),Cursor 作为现场交互工程师专注秒级局部编辑;提出按任务切片动态切换的三种工程化协作场景,并给出结构化上下文构建、约束型 Prom

weixin_28728443的博客 123

RTT Studio和Cubemx联合开发

1. RTT studio创建工程 创建工程 ## 创建完成以后的目录结构 2. 配置CubuMx 双击cubumx的图标打开CubeMx 配置时钟 生成代码 构建后的代码结构 编译代码满屏错误:不要慌 3. 新增脚本 新建scons脚本文件 SConscript 脚本内容如下 import os from building import * cwd = GetCurrentDir() src = Glob('*.c') # add cubemx drivers src = Split('''

Car12 1565

【C++进阶系列】:万字详解红黑树(附模拟实现的源码)

想要学会红黑树?看这篇文章就够了!万字详解

努力努力再努力wz的博客 1406

书旗app字符串加密分析

本文案例是对书旗app搜索接口的请求密文进行分析和逆向。

李玺 3156

手把手教你实现红黑树

手把手教你实现AVL树、平衡二叉树红黑树是在1972年由发明的。其特点是从根到叶子节点的所有路径中,最长路径不大于最短路径的2倍。可以说红黑树是AVL树的plus版,因此,红黑树查找时间与AVL树相同,都为O(log N)。同时,红黑树没有做到AVL树那种绝对平衡,因此其旋转次数少于AVL树。当数据量大时,其效率要优于AVL树。正因如此,在实际应用中往往采取红黑树而非AVL树。

weixin_61857742的博客 2878

在 RAP 中把业务对象“搬到网口上”:service definition 与 service binding 的全流程、范式与实战

本文解析了SAP ABAP开发中service definition和service binding的关键作用。service definition负责选择要暴露的CDS实体和行为,形成服务模型;而service binding则将服务绑定到具体协议(如OData),生成可访问的端点。两者分离带来三大优势:支持同一模型多重发布、降低环境迁移耦合度、强化安全治理。文章通过预订业务对象的端到端示例,展示了如何从CDS建模到生成Fiori Elements预览。最后以售后工单业务为例,说明这种架构如何支持内外服务

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 390

SAP 基于生产订单行项目外部加工创建采购申请时的一个增强需求

摘要 本文介绍在SAP系统中实现生产订单外协工序自动生成采购申请(PR)时,将指定文本写入PR抬头文本的技术方案。关键点包括: 业务背景:通过CO02事务码将工序标记为外部加工,系统自动生成PR,需在生成时自动写入抬头文本。 技术难点: PR抬头文本存储在STXH/STXL而非EBAN表 标准增强点ME_PROCESS_REQ_CUST在外协场景可能不触发 推荐方案: 使用BAdI ME_REQ_POSTED,在PR过账时点执行 通过Text Object EBANH和Text ID(如B01)写入文本 实

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 623

【数据结构】红黑树实现详解

红黑树是一棵二叉搜索树,它的结点不是黑的就是红的,其中它有一个非常重要的通过对任何一条从根到叶子的路径上各个结点的着色控制,保证了红黑树没有一条路径会比最短路径长出两倍,达到接近平衡的特点。看到这句话,可能你还云里雾里的,但是不要怕,简单的来说,红黑树的特点就是:找出树中最短的路径和最长的路径,其中这条最长路径的长度不会大于最短路径长度的两倍。如下图所示:在这棵红黑树中,最短的路径是最左边的那条,长度为3,最长的路径是最右边的那条,长度为4,即4 < 2*3,最长的路径不会大于最短路径的两倍。

EWIAW_ilove的博客 1280

PCL 计算点云的体积密度(C++详细过程版)

本文提出了一种基于点云体积密度的计算与可视化方法。算法通过KdTree搜索每个点的邻域,利用球体积公式计算单位体积内的点数作为密度值,并存储在点云强度属性中。代码实现了点云读取、密度计算和可视化功能,使用PCL库完成邻域搜索和密度渲染。结果显示,该方法能有效反映点云密度分布,为后续点云处理提供密度特征参考。文章附有完整C++代码实现和可视化效果图,适用于点云密度分析和特征提取应用。

点云侠的博客 308

C++ 红黑树封装(一):从 SGI-STL 源码理解如何用一棵红黑树实现 map 和 set

插入查找自动平衡但如果停留在这里,它仍然只是一种数据结构。setmapmultisetmultimap容器封装set<int> s;set 存 keymap 存 key-value看起来完全不是一种数据结构。但实际上,它们有一个非常重要的共同点:都需要按照 key 进行有序存储和搜索。set红黑树map完全可以共用一套红黑树实现。真正困难的问题因此变成:如何设计一棵足够泛型的红黑树,让它既能保存K,又能保存pair<K,V>?这正是这一篇文章要解决的问题。

Face_FeaR的博客 6284

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

红黑树(三) 之 C++ STL模板实现(完整源码)

使用C++模板实现红黑树

Manofletters的博客 662

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

【c++丨STL】基于红黑树模拟实现set和map(附源码)

本篇文章,基于之前实现的红黑树代码,我们将仿照SGI STL的实现方式,尝试对同一棵红黑树进行封装和一系列适配修改,模拟实现set和map两种容器。

2301_80955819的博客 1390

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

c++STL——红黑树封装set与map:深入源码解析

c++STL——红黑树封装map和set

2301_79705195的博客 1013

红黑树的原理和实现(STL源码剖析/C++)

红黑树的定义 每个节点要么是红色,要么是黑色 根节点是黑色 所有叶子节点(NULL)为黑色 (这里的叶子节点是指空节点NIL或者NULL,可以理解为虚拟的叶子节点) 如果一个节点是红色,则它的子节点必须是黑色的(没有两个相邻的红色节点) 从一个节点到该节点的子孙节点的所有路径有相同数目的黑色节点 (保证最长路径不会超过最短的两倍) 红黑树的时间复杂度 红黑树的时间复杂度O(logn) 红黑树的查找、插入、删除都可以在O(logn)内完成 定理:一棵含有n个节点的红黑树的高度至多为2log(n+1).

qq_42007287的博客 1063

【C++进阶】手撕 STL 源码:用红黑树封装实现 Map 和 Set

本文介绍如何通过改造红黑树模板,使其能同时支持Map和Set的实现。关键点在于: 引入KeyOfT仿函数,从存储类型T中提取键值K 红黑树模板参数调整为<K, T, KeyOfT> Set直接存储K,Map存储pair<K,V> 通过迭代器封装控制元素的可修改性 最终实现一套RBTree底座衍生出Map和Set两种容器,体现了STL中泛型编程的精妙设计。

2301_80127108的博客 765

在STL源码当中,如何使用一颗红黑树同时实现map和set的?

在STL源码当中,如何使用一颗红黑树同时实现map和set的?

AkieMo的博客 311

底层实现红黑树_干货 | 名企高频考点之STL map你看过map底层红黑树的源码吗?...

点击蓝字关注我哦以下是本期干货视频视频后还附有文字版本哦▼《STL map的底层实现原理之代码探秘》▼ps:请在WiFi环境下打开,如果有钱任性请随意了解了红黑树,也知道了如何做出平衡调整,这就意味着我们具备了探究红黑树代码的资本,本小节我们从调试的角度,带着大家探究一下红黑树的重要接口,以及探究map结构是如何在红黑树的基础上来进行实现的。红黑树的重要接口 template<cl...

weixin_39594296的博客 266

【红黑树进阶】手撕STL源码:从零封装RB-tree实现map和set

本文深入剖析STL底层设计思想,带你手把手将红黑树封装成自己的map和set。核心内容包括:KeyOfT仿函数解决比较问题、迭代器的完整实现(++/--操作)、map的operator[]重载、const迭代器与const正确性保证。通过完整的代码实现(RBTree.h/Myset.h/Mymap.h),让你彻底理解STL中map/set的复用机制。适合有一定红黑树基础,想深入掌握STL源码精髓的开发者,建议结合源码学习!

燃于AC之乐的博客 879

深入STL源码:从vector内存管理到map红黑树实现

标准模板库(STL)是C++编程的核心组件,其设计融合了数据结构、算法和泛型编程的精髓。理解STL的内部工作原理,不仅能帮助开发者编写更高效的代码,还能深入掌握内存管理、迭代器失效等底层机制。通过分析vector的动态数组实现,可以了解其容量增长策略和内存重分配过程;而map基于红黑树的结构,则展示了自平衡二叉搜索树如何保证O(log n)的操作复杂度。这些知识对于优化程序性能、调试复杂问题至关重要。在实际开发中,掌握STL源码有助于更好地使用容器和算法,例如通过reserve预分配vector内存,或根据

ainixi7099的博客 383

STL源码——关联式容器及其底层红黑树实现(下) 之 红黑树的剖析(插入,删除操作)

代码其实就是按着平衡策略实现的,而硬记住这个策略略微空洞且为难,那么重点就应该是知道“为什么要这样调整”

qq_37299596的博客 336

C++ STL之封装红黑树实现map/set

本文通过分析STL源码,深入解析了红黑树封装map/set的实现机制。首先介绍了源码中map和set头文件的结构,重点解析了红黑树模板参数的设计,特别是KeyOfValue参数的作用。接着详细说明了红黑树结点的修改方案,包括使用模板参数T代替具体类型以支持泛型编程。文章还深入探讨了红黑树迭代器的实现,特别是operator++和operator--的中序遍历逻辑。最后给出了完整的模拟实现代码,包括RBTree.h、my_set.h和my_map.h三个文件,展示了如何通过一棵红黑树同时支持set和map的功

2301_79976271的博客 1113
上一篇: x265-common.h
下一篇: STL-String源码分析
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值