红黑树

【树形结构】红黑树 {概念及性质;红黑树的结构;带头结点的红黑树;红黑树的实现;红黑树插入操作详细解释;红黑树的验证} 阅读详情

一、红黑树性质

二叉搜索树中若一个节点没有父节点或子节点则该节点相应属性的值设为NIL,我们视NIL为二叉搜索树的叶节点(外部节点),带关键字的为内部节点。一棵红黑树是满足下列五条性质的二叉搜索树:
1. 树的每个节点不是红色就是黑色
2. 树的根节点是黑色
3. 树的每个叶节点(NIL)为黑色
4. 若节点是红色则它的孩子必须是黑色(若有孩子的话)
5. 树中每一个节点到其后代叶节点的路径上黑色节点的数目相同

红黑树
红黑树黑高的定义:从某个节点出发(不包含此节点)到达其后代叶节点的路径上黑色节点数目称为此节点的黑高,由性质5知节点到其每个后代叶节点的路径上的黑色节点数目是相同的,因此红黑树的黑高可以定义为根节点的黑高。

定理:一棵具有n个内部节点的红黑树的树高至多是2lg(n+1)
证明: 证明以任一节点x为根的红黑树至少有2^bh(x)-1个内部节点。(bh(x)为节点x的黑高)数学归纳法证明:当bh(x)=0,x为叶节点,则x有0个内部节点,命题成立。当bh(x)=1,则x有1个内部节点,命题成立。考虑一个高度为正值且有两个孩子的内部节点x,其黑高为bh(x)它的孩子的黑高为bh(x) 或bh(x)-1(具 体取那个值与X自身的颜色有关),根据命题节点x的每个孩子至少包含2^(bh(x)-1)-1个内部节点,于是,以x为根的子树至少包含2^(bh(x)-1)-1+2^(bh(x)-1)-1+1=2^bh(x)-1个内部节点。命题证明完毕,设树的高度为h,由红黑树性质4知道从根到叶节点(不包括根节点)的任一条路径至少有一半的节点为黑色,因此,根的黑高bh(x)>=h/2,所以由n>=2^bh(x)-1>=2^(h/2)-1,因此可得h<=2lg(n+1)。

注意:通过对任一一条从根到叶节点的简单路径上各个节点颜色的约束,红黑树确保没有一条路径会比其他路径长出2倍,因此红黑树是近似平衡的。

备注:
红黑树和AVL树(平衡二叉树)的区别在于它使用颜色来标识结点的高度,它所追求的是局部平衡而不是AVL树中的非常严格的平衡

参考:
平衡二叉树(AVL)

二、旋转

旋转图

  1. 左旋转
left-rotated(T, x)
{
    y = x.right;
    x.right = y.left;
    if(y.left!=T.nil)
    {
        y.left.p = x;
    }
    y.p = x.p;
    if(x.p == T.nil)
    {
        T.root = y;
    }
    else if(x == x.p.left)
    {
        x.p.left = y;
    }
    else if(x == x.p.right)
    {
        x.p.right = y;
    }

    y.left = x;
    x.p = y;
}
  1. 右旋转
right-rotated(T, y)
{
    x = y.left;
    y.left = x.right;
    if(x.right!=T.nil)
    {
        x.right.p = y;
    }
    x.p = y.p;
    if(y.p == T.nil)
    {
        T.root = x;
    }
    else if(y == y.p.left)
    {
        y.p.left = x;
    }
    else if(y == y.p.right)
    {
        y.p.right = x;
    }
    x.right = y;
    y.p = x;
}

注意:为防止遗漏了指针的赋值,可以查看旋转时都哪些节点的left,right,p指针值发生了变化。
参考:《算法导论》第十三章红黑树上面旋转部分的图

三、插入

插入图

rb_insert(T, z)
{
    y = T.nil;
    x = T.root;
    while(x!=T.nil)
    {
        y = x;
        if(z.key<x.key)
        {
            x = x.left;
        }
        else
        {
            x = x.right;
        }
    }
    z.p = y;
    if(y==T.nil)
    {
        T.root = z;
    }
    else if(z.ley<y.key)
    {
        y.left = z;
    }
    else
    {
        y.right = z;
    }
    z.clolr = RED;
    z.left = T.nil;
    z.right = T.nil;

    rb_insert_fixup(T, z);
}


rb_insert_fixup(T, z)
{
    while(z.p.color=RED)
    {
        if(z.p==z.p.p.left)
        {
            y = z.p.p.right;
            if(y.color==RED)
            {
                z.p.color = BLACK;              //case1
                y.color = BLACK;                //case1
                z.p.p.color = RED;              //case1
                z = z.p.p;
            }
            else 
            {
                if(z==z.p.right)
                {
                    z = z.p;                    //case2
                    left_rotated(T,z);          //case2
                }
                z.p.color = BKACK;               //case3
                z.p.p.color = RED;               //case3
                right_rotated(T,z.p.p);          //case3
            }
        }
        else  // z.p==z.p.p.right
        {
            y = z.p.p.left;
            if(y.color==RED)
            {
                z.p.color = BLACK;                 //case1
                y.color = BLACK;                   //case1
                z.p.p.colr = RED;                  //case1
                z = z.p.p;                         //case1
            }
            else
            {
                if(z==z.p.left)
                {
                    z = z.p;                       //case2
                    right_rotated(T, z);           //case2
                }
                z.p.color = BLACK;                 //case3
                z.p.p.color = RED;                 //case3
                left_rotated(T,z.p.p);             //case3
            }
        }
    }
    T.root.color = BLACK;
}

参考《算法导论》第十三章 图13-4帮助理解代码。

对于插入的节点z为什么着色为红色RED,而不是黑色BLACK,个人理解如下:
1. 着色为红色RED不会破坏红黑树性质5。
2. 若着色为黑色就需要调整z节点以上的许多节点从新平衡树,调整量大。
3. 着色为红色只需沿着z向上调整,调整量下;在调整颜色时在case1中是两层两层向上升的,只要有一次进入case2或case3就表示调整结束。

四、删除

删除操作

rb_transplant(T, u, v)
{
    if(u.p == T.nil)
    {
        T.root = v;
    }
    else if(u.p.left == u)
    {
        u.p.left = v;
    }
    else
    {
        u.p.right = v;
    }
    v.p = t.p;
}

//保持红黑树性质 
rb_delete_fixup(T, x)
{
    while(x!=T.root && x.color == BLACK)
    {
        if(x == x.p.left)
        {
            w = x.p.right;
            if(w.color == RED)
            {
                w.color = BLACK;                 //case1
                x.p.color = RED;                 //case1
                left_rotated(T, x.p);            //case1
                w = x.p.right;                   //case1
            }
            else if(w.color == BLACK)
            {
                if(w.left.color == BLACK 
                && w.right.color == BLACK)
                {
                    w.color = RED;                //case2
                    x = x.p;                      //case2
                }
                else 
                {
                    if(w.right.color == BLACK)
                    {
                        w.left.color = BLACK;    //case3
                        w.color = RED;           //case3
                        right_rotated(T, w);     //case3
                        w = x.p.right;           //case3
                    }
                    w.color = x.p.color;        //case4
                    x.p.color = BLACK;          //case4
                    w.right.color = BLACK;      //case4
                    left_rotated(T, x.p);       //case4
                    x = T.root;
                }
            }
        }
        else if(x == x.p.right) //和以上是对称的 
        {
            w = x.p.left;
            if(w.color == RED)
            {
                w.color = BLACK;
                x.p.color = RED;
                right_rotated(T, x.p);
                w = x.p.left;
            }
            else if(w.color == BLACK)
            {
                if(w.left.color == BLACK 
                && w.right.color == BLACK)
                {
                    w.color = RED;
                    x = x.p;
                }
                else
                {
                    if(w.left.color == BLACK)
                    {
                        w.right.color = BLACK;
                        w.color = RED;
                        left_rotated(T, w);
                        w = x.p.left;
                    }
                    w.color = x.p.color;
                    x.p.color = BLACK;
                    w.left.color = BLACK;
                    right_rotated(T, x.p);
                    x = T.root;
                }
            }
        }
    }
    x.color = BLACK;
}

//删除操作 
rb_delete(T,z)
{
    y = z; //当z只有一个孩子时y,z指向同一个节点
    y_original_color = y.color;
    if(z.left == T.nil) 
    {
        x = z.right;
        rb_transplant(T, z, z.right);
    }
    else if(z.right == T.nil)
    {
        x = z.left;
        rb_transplant(T, z, z.left);
    }
    else 
    {
        //寻找z右子树上的最小值也即z的后继节点
        y = tree_minmum(z.right);
        y_original_color = y.color;
        x = y.right;
        if(y.p == z) 
        {
            //这一步是必要的也即当x时叶节点时也把其父节点指针赋值为y 
            //这是为了rb_delete_fixup(T, x)中保持红黑树性质的需
            //要
            x.p = y;
        }
        else 
        {
            rb_transplant(T, y, y.right);
            y.right = z.right;
            y.right.p = y;
        }
        y.left = z.left;
        y.p = z.p;
        y.color = z.color;
    }
    if(y_original_color == BLACK)
    {
        rb_delete_fixup(T, x);
    }
} 

对于rb_delete(T,z)可能比较好理解但是对于rb_delete_fixup(T,x)就不是很好理解了。虽然说是删除z节点但是其实是把y节点的值赋值给了z节点真正删除的是y节点,而x节点占据了y节点原来的位置。若删除的y节点是黑色的那就破坏了红黑树的性质5。算法中是将y的黑色“下推”给节点x。使节点x成为双重颜色(黑黑或红黑),然后再rb_delete_fixup中将x节点上的双重性去掉,去掉的方法是从x节点向上通过一系列的旋转和重新赋值在某一层上找到一个红色节点将其赋值为黑色来弥补由于删除y节点而导致的某些路径的黑高比其他的低一个单位(这里利用了红黑树的黑色节点的孩子可以是红色也可以是黑色,但是红色节点的孩子必须是黑色)。

个人关于红黑树的理解 目录   红黑树(red-black-tree) 一.红黑树的定义和性质 二.红黑树的结构 三.输出一颗红黑树 四.查询红黑树 查找 查找最大关键字元素和最小关键字元素 查找前驱和后继 五.※插入和删除 插入 删除 六.完整代码 红黑树(red-black-tree) 一.红黑树的定义和性质 红黑树是一种二叉查找树,在每个结点上增加一个存储位表示结点的颜色,,可以是... 阅读详情

相关推荐

红黑树解析

写在前面:我是「且听风吟」,目前是某上市游戏公司的大数据开发工程师,热爱大数据开源技术,喜欢分享自己的所学所悟,现阶段正在从头梳理大数据体系的知识,以后将会把时间重点放在Spark和Flink上面。 如果你也对大数据感兴趣,希望在这个行业一展拳脚。欢迎关注我,我们一起努力,一起学习。博客地址:https://ropledata.blog.youkuaiyun.com 博客的名字来源于:且听风吟,静待花开。也符合我对技术的看法,想要真正掌握一门技术就需要厚积薄发的毅力,同时保持乐观的心态。 你只管努力,剩下的交给.

静待花开 2232

红黑树定理证明

定理证明 基本概念 树的深度和高度: 树的深度是从根节点开始(其深度为1)自顶向下逐层累加的,而高度是从叶节点开始(其高度为1)自底向上逐层累加的。 证明:内部节点最多,内部节点最少 如果一棵红黑树的黑高为 k,则其内部节点最多为,做少为: 内部节点最多时的情形为:任何一个简单路径上,黑红黑红黑宏,的循环排列, 此时红色节点数目达到最大,树高也达到最大,最大为:2k,此时内部节点为:22k−12^...

菜不是原罪 1415

暗月项目七详解

本文围绕“暗月靶场项目七”展开,记录了一次从外网 Web 入口逐步深入内网并最终获取域控目标的完整实训过程。

Re_K123的博客 419

红黑树的由来,特性,原理以及适用场景分析

注意:本文不涉及红黑树的具体实现,并且默认读者已经对二叉树,二叉查找树,AVL树等已经了解并熟悉。 一、平衡二叉查找树 定义:树中任意一个节点的左右子树高度差不大于1。 AVL树是一种严格按照定义来实现的平衡二叉查找树,所以,它的查找效率非常稳定,是O(log n),由于严格按照左右子树高度差不大于一的规则,插入和删除操作中需要大量的操作来保持树的平衡,比较耗时。 因此,AVL树适用于大量查询,少...

Alan-zzx的博客 2973

保姆级教程:用Smaart7和你的USB声卡搞定现场音响系统调试(附频谱与延时测试避坑指南)

本文提供Smaart7与USB声卡协同工作的现场音响系统调试指南,涵盖硬件连接、频谱分析、延时校准等关键步骤。通过详细的操作流程和常见问题解决方案,帮助音响工程师快速掌握专业测量技术,确保演出音质达到最佳状态。

weixin_29290259的博客 425

C# chart以鼠标所在位置为中心进行缩放

以前都用labview做一些软件,但给出去总是会遇到版本,安装包过大等一些问题,于是想自学C#,记录一下使用过程中遇到的一些问题和解决措施,便于日后回顾。 在这个项目中需要绘制折线图,由于数据比较大,需要对图表进行缩放操作,以鼠标为中心对图表进行缩放,在网上查找了一些资料没找到我想要的,于是自己想了一个解决方案,可以基本实现,但略显繁琐,由于刚开始学习C#,对一些操作不太了解,若以后遇...

fei的博客 6363

红黑树 原理和算法详细介绍(Java)

R-B Tree简介R-B Tree,全称是Red-Black Tree,又称为“红黑树”,它一种特殊的二叉查找树。红黑树的每个节点上都有存储位表示节点的颜色,可以是红(Red)或黑(Black)。红黑树的特性:(1)每个节点或者是黑色,或者是红色。 (2)根节点是黑色。 (3)每个叶子节点(NIL)是黑色。 [注意:这里叶子节点,是指为空(NIL或NULL)的叶子节点!] (4)如果一个节点

Code-lover's Learning Notes 4212

CS231n+assignment2(一)

cs231n作业二详解+代码

qq_56551150的博客 2411

红黑树介绍

红黑树一、红黑树的概念红黑树的性质红黑树节点的定义红黑树结构二、使用步骤1.引入库2.读入数据总结 一、红黑树的概念 红黑树,是一种二叉搜索树,但在每个结点上增加一个存储位表示结点的颜色,可以是Red或Black。 通过任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树确保没有一条路径会比其他路径长出俩倍,因而是接近平衡的。 红黑树的性质 每个结点不是红色就是黑色 根节点是黑色的 如果一个节点是红色的,则它的两个孩子结点是黑色的 对于每个结点,从该结点到其所有后代叶结点的简单路径上,均 包含相同数

mz474920631的博客 4万+

Anomalib实战:从零开始构建自定义数据集的异常检测模型

本文详细介绍了如何使用Anomalib 2.1.0从零开始构建自定义数据集的异常检测模型。通过实战演示,指导读者准备符合规范的数据集结构,快速上手训练Patchcore等先进算法,并完成模型推理与调优,为工业质检、医疗影像等场景提供高效的视觉异常检测解决方案。

weixin_29165465的博客 109

Widar3.0复现日志(DFSExtractionCode)

需要使用的matlab基本功能

XiaoQiXiaoWei_J的博客 2439

【C++】红黑树

因为每个节点都存在颜色,并且不为黑色就为红色,所以我们可以定义一个表示颜色的枚举常量。红黑树依旧是三叉链。

bushibrnxiaohaij的博客 2965

BW 技术 InfoObject 初始化,一次把 0LANGU、0CURRENCY、0IOBJNM 这些底座对象讲透

摘要:BW/4HANA和S/4HANA嵌入式分析中最容易被忽视的关键技术InfoObject(如0LANGU、0UNIT等)是系统运行的基础骨架。这些对象虽不直接涉及业务,但若未正确激活会导致多维分析、查询运行等核心功能异常。BW/4HANA中应通过任务清单SAP_BW4_SETUP_SIMPLE或SAP_BW4_SET_OPERATION_SCOPE激活,而非旧事务码RSTCO_ADMIN。S/4HANA嵌入式分析仍需依赖这些底层BW组件,配置需参考SAP Note 2636754。项目实践中需特别关注这

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

红黑树原理详解

   二叉查找树由于在频繁的动态更新过程中,可能会出现树的高度远大于 log2n的情况,所以就会导致各个操作效率下降,最坏的情况下就会退化为链表,变为O(n).很明显,想要解决这个问题,有效的一种办法就是使得树的高度不要差很多,也就是平衡它.     最先发明的平衡二叉查找树是AVL树,(它严格符合平衡二叉查找树的定义,即任何节点的左右子树高度相差不超过 1,是一种高度平衡的二叉查找树。)但是在...

Tattoo的博客 3万+

风控域——知识图谱相关原理

本文全面介绍了知识图谱在风控领域的应用原理。从基础知识入手,阐述了知识图谱的定义、概念及应用场景,重点聚焦于金融风控。进一步讲解了知识图谱的技术架构,涵盖计算、融合与构建等方面。深入探讨了知识表示、建模、抽取、挖掘、存储、融合、检索和推理等关键技术原理,并结合金融风控实际需求,详细说明了各技术环节的具体应用方法与流程,为构建高效风控知识图谱提供了理论与实践指导。

庄小焱 612

jre9下载 jdk9

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

【C++】————红黑树

RED,BLACK, _kv(kv){}private:_left、_right 和 _parent 分别指向节点的左子节点、右子节点和父节点。_kv 是一个 pair,存储节点的键和值。_col 表示节点的颜色,可以是 RED 或 BLACK。接收一个 pair 作为参数,初始化节点的键值对,并将节点的颜色初始化为 RED。其他指针成员初始化为 nullptr。

bhbcdxb123的博客 2167

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

C++——红黑树

C++之红黑树板块讲解

dongxue727504的博客 3280

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

【C++】——红黑树(手撕红黑树,彻底弄懂红黑树)

我们之前都学过ALV树,AVL树的本质就是一颗平衡二叉树,它的作用就是查找,插入和删除节点,最坏的时间复杂度都是O(logn)的,同时维护的高度差都是小于等于1的,但是也就是因为这个原因才被红黑树所替代红黑树是一种自平衡的二叉查找树,是一种高效的查找树。它是由 Rudolf Bayer 于1978年发明,在当时被称为平衡二叉 B 树(symmetric binary B-trees)。后来,在1978年被 Leo J. Guibas 和 Robert Sedgewick 修改为如今的红黑树。

m0_74092462的博客 2087

C++中红黑树的实现 -- 红黑树的概念,红黑树的规则,红黑树插入时的情况分析,红黑树的实现,红黑树的查找,红黑树的验证

红黑树是一种自平衡二叉搜索树,通过颜色约束确保最长路径不超过最短路径的两倍。其核心规则包括:根节点为黑色、红色节点不能连续、每条路径黑色节点数相同。插入操作涉及变色和旋转两种调整方式,根据叔叔节点颜色分为不同处理情况。与AVL树相比,红黑树平衡要求较宽松,旋转次数更少,但查找效率相近(O(logN))。本文详细介绍了红黑树的结构定义、插入逻辑(包括单旋和双旋场景)、验证方法,并提供了与AVL树的性能对比测试代码,显示两者在百万级数据下的操作耗时相当。

CSQCSQCC的博客 1615

红黑树系列1——红黑树的建立

原创码字不易,转载请注明出处,谢谢~ 红黑树系列2——红黑树的删除(码字中,待发表) 红黑树系列3——红黑树的应用(码字中,待发表) 红黑树系列4——红黑树的代码实现(码代码中,待发表) 红黑树动态建立,删除网站(强强强强烈推荐,根据网页上自己构建和删除几遍红黑树,比看文章有用太多太多):https://www.cs.usfca.edu/~galles/visualization/RedBlack.html 目录 一、红黑树的建立 1、建立红黑树 例子1、解决连续右右红色节点 例子2、解决

Bob的博客 2831

C++之红黑树

红黑树,是一种二叉搜索树,但在每个结点上增加一个存储位表示结点的颜色,可以是Red或Black。 通过对任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树确保没有一条路径会比其他路径长出俩倍,因而是接近平衡的。 4.2.2 红黑树的性质 1. 每个结点不是红色就是黑色 2. 根节点是黑色的 3. 如果一个节点是红色的,则它的两个孩子结点是黑色的,但是没有连续的红节点 4. 对于每个结点,从该结点到其所有后代叶结点的简单路径...

cls的博客 2399
上一篇: NYOJ 304 节能
下一篇: 条款25:考虑写一个不抛出异常的swap函数
知行且执行
博客等级 码龄14年 38粉丝 73原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值