红黑树的基本概念

红黑树
  • 请添加图片描述

  • 特征

    • [1] 根节点是黑色的
    • [2] 每个叶子节点都是黑色的空节点(NIL), 也就是说,叶子节点不存储数据
    • [3] 任何相邻的节点都不能同时为红色,也就是说,红色节点是被黑色节点隔开的
    • [4] 每个节点,从该节点到达其可达叶子节点的所有路径,都包含相同数目的黑色节点
为什么说红黑树是“近似平衡”的?
  • 平衡的意思可以等价为性能不退化
  • 近似平衡就是等价为性能不会退化太厉害
  • 二叉查找树很多操作的性能都跟树的高度成正比
    • 一颗极其平衡的二叉树(满二叉树或完全二叉树)的高度大约是log2n
    • 所以,如果要证明红黑树是近似平衡的,只需要分析,红黑树的高度是否比较稳定地趋近log2n就好了
  • 红黑树高度分析
    • 请添加图片描述

    • 如果,把红色节点从红黑树中去掉,那单纯包含黑色节点的红黑树的高度是多少?

      • 红色节点删除之后,有些节点就没有父节点了,它们会直接拿这些节点的祖父节点(父节点的父节点)作为父节点。所以,之前的二叉树就会变成四叉树
      • 前面红黑树的定义有一条:从任意节点到可达的叶子节点的每个路径包含相同数目的黑色节点。从四叉树中取出某些节点,放到叶节点位置,四叉树就变成完全二叉树。所以,仅包含黑色节点的四叉树的高度,比包含相同节点个数的完全二叉的高度还要笑
      • 完全二叉树的高度近似log2n,这里的四叉“黑树”的高度要低于完全二叉树,所以去掉红色节点的“黑树”的高度也不会超过log2n
      • 原红黑树中。红色节点不能相邻,也就说,有一个红色节点就要至少有一个黑色节点,将它跟其他红色节点隔开。红色树中包含最多黑色节点的路径不会超过log2n,所以加入红色节点之后,最长路径不会超过2log2n也就是说红黑树的高度近似2log2n
红黑树操作项
  • 左旋(rotate left)
    • 左旋全称,围绕某个节点的左旋

    • 请添加图片描述

    • X的右子节点成为X的父节点。也即X成为左子节点

  • 右旋(rotate right)
    • 右旋全称,围绕某个节点的右旋

    • 请添加图片描述

    • X的左子节点成为X的父节点。也即X成为右子节点

  • 插入操作的平衡调整
    • 红黑树规定,插入的节点必须是红色。二叉查找树中新插入的节点都是放在叶子节点上
      • 如果插入节点的父节点是黑色,那什么都不用做,它仍然满足红黑树的定义
      • 如果插入的节点是根节点,那直接改变它的颜色,把它变成黑色
    • 如果存在违背红黑树的定义,就需要左右旋转改变颜色做调整
    • 红黑树的平衡调整过程是一个迭代的过程
      • 把正在处理的节点叫做关注节点
      • 关注节点会随着不停迭代处理,而不断发生变化。最开始的关注节点就是新插入的节点
    • 插入平衡调整策略
      • CASE 1: 如果关注节点a,它的叔叔节点d是红色
        • 请添加图片描述

        • 操作策略

          • 将关注节点a的父节点b, 叔叔节点d的颜色都设置成黑色
          • 将关注节点a的祖父节点c设置成红色
          • 关注节点变成a的祖父节点c
          • 跳到CASE 2CASE 3
        • 策略说明

          • a 和 b都是红色,违背了特征[3]. 把b设置成黑色以解决问题
          • b 从 红色变成了黑色,违背了特征[4].所以要把c设置红色
          • 因为a,c都改变了颜色。导致 d节点分支的黑色节点总数减少了1,违背了特征[4].所以d要变成黑色
      • CASE 2: 如果关注节点是a,它的叔叔节点d是黑色,关注节点a是其父节点b的右子节点
        • 请添加图片描述

        • 操作策略

          • 关注节点变成节点a的父节点b
          • 围绕新的关注节点b左旋
          • 跳到CASE 3
        • 策略说明

          • 处理红黑树的核心思想:将红色的节点移到根节点,然后将根节点设为黑色
          • 所以要不断将破坏红黑树特性的红色节点上移。即通过左旋将a上移
          • 如果a变成了根节点,可以直接变黑色.如果不是根节点,就需要切换关注节为b
          • 处理问题准则
            • 需要从下至上(由叶到根)方向处理
            • 必须先解决子节点的问题,再解决父节点问题
      • CASE 3: 如果关注节点是a,它的叔叔节点d是黑色,关注节点a是其父节点b的左子节点
        • 请添加图片描述

        • 操作策略

          • 围绕关注节点a的祖父节点c右旋
          • 将关注节点a的父节点b,兄弟节点c的颜色互换
          • 调整结束
        • 策略说明

          • b 和 a都是红色,违背了特征[3]
          • 所以把b,c颜色互换。b为黑色, c为红色。然后以c右旋
            • b设置为黑色,解决了特征[3]
            • b为黑色后,所有经过b的黑色节点数量增加了1,违背了特征[4],要把c改成红色,
            • 但是经过d的黑色节点数量减少了1,然后以c右旋
    • 删除平衡调整
      • 删除平衡调整分两步
        • 针对删除节点初步调整
          • 将红黑树当作一颗二叉查找树,将节点删除后,可能违反特征[1], 特征[3], 特征[4]
          • 对于删除的某节点(删除节点y,新节点x)
            • 删除节点y之后,x占据了原来节点y的位置
            • 既然删除y(y是黑色),意味着减少一个黑色节点,那在该位置上增加一个黑色即可
            • 假设"x包含一个额外的黑色",就正好弥补了"删除y所丢失的黑色节点",就不会违反特征[4]
            • 还有,假设"x包含一个额外的黑色"(x原本颜色还存在),这样也不会违反特征[4]
            • 现在,x不仅包含原本的颜色属性,x还包含一个额外的黑色。即x的颜色属性是"红 + 黑" 或 “黑 + 黑”,违反特征[3]
        • 针对关注节点进行二次调整
          • 二次调整是为了解决违反特征[3],特征[4]这2个特征
          • 调整方法(x为需要调整的节点):将x所包含的额外的黑色不断沿树上移(向根方向移动)
            • x是 "红 + 黑"节点,x为叶子节点
              • 直接把x设为黑色,结束。此时红黑树性质全部恢复
            • x是 "黑 + 黑"节点,且x是根
              • 什么都不做,结束。此时红黑树性质全部恢复
            • x是"黑 + 黑"节点,且不是根
              • 可以划分出四种子情况
      • 针对删除节点初步调整
        • 删除简述
          • 被删除节点没有儿子,即为叶节点。那么,直接将该节点删除就OK了
          • 被删除节点只有一个儿子。那么,直接删除该节点,并用该节点的唯一子节点顶替它的位置
          • 被删除节点有两个儿子
            • 先找出它的后继节点,然后把‘它的后继节点的内容’复制给‘该节点的内容’,之后,删除‘它的后继节点’
        • CASE 1: 如果要删除的节点是a, 它只有一个子节点b
          • 请添加图片描述

          • 操作策略

            • 删除节点a,并且把节点替换到a的位置,这一部分操作跟普通的二叉查找树的删除操作一样
            • 节点a只能是黑色,节点b也只能是红色,其他情况均不符合红黑树的定义。这种情况下,我们把节点b改成黑色
            • 调整结束,不需要进行二次调整
          • 策略说明

            • 被删除节点只有一个儿子
            • 那么,直接删除该节点,并用该节点的唯一字节点顶替他的位置
        • CASE 2: 如果要删除的节点a有两个非空子节点,并且它的后继节点就是节点a的右子节点c
          • 请添加图片描述

          • 操作策略

            • 如果节点a的后继节点就是右子节点c,那右子节点肯定没有左子树。我们把节点a删除,并且将节点c替换到节点a的位置。这一部分操作跟普通的二叉树的删除操作无异
            • 然后把节点c的颜色设置为跟节点a相同的颜色
            • 如果节点c是黑色,为了不违反红黑树的特征[4],我们给节点c的右子节点d多加一个黑色,节点d就成了"红 - 黑""黑 - 黑"
            • 同时关注节点变成了节点d,第二步的调整操作就会针对关注节点来做
          • 策略说明

            • 被删除的节点有两个儿子。那么,先找出它的后继节点
            • 然后把“它的后继节点的内容”复制给“该节点的内容”
            • 之后,删除“它的后继节点”。在这里,后继节点详单于替身,在将后继节点的内容复制给“被删除节点”之后,再将后继节点删除
            • 这样就巧妙的将问题转换为“删除后继节点”的情况了
            • 后面只需要考虑后继节点的情况
        • CASE 3: 如果要删除的是节点a,它有两个非空子节点,并且节点a的后继节点不是右子节点
          • 请添加图片描述

          • 找到后继节点d,并将它删除,删除后继节点d的过程参照CASE 1

          • 将节点a替换成后继节点d

          • 把节点d的颜色设置为跟节点a相同的颜色

          • 如果节点d是黑色,为了不违法特征[4],我们给节点d的右子节点c多加一个黑色,这个时候节点c就变成了"红 - 黑" 或者 "黑 - 黑"

          • 这个时候,关注节点变成了节点c,第二步的调整操作就会针对关注节点来做

      • 针对关注节点进行二次调整
        • 经过初步调整之后,关注节点变成了“红 - 黑” 或者 “黑 - 黑”
        • CASE1: 如果关注节点是a,它的兄弟节点c是红色
          • 请添加图片描述

          • 操作策略

            • 围绕关注节点a的父节点b左旋
            • 关注节点a的父节点b和祖父节点c交换颜色
            • 关注节点不变
            • 继续从四种情况中选择合适的规则来调整
          • 策略说明

            • 这样做的目的是将CASE 1 转换为CASE 2, CASE 3CASE 4从而进一步处理
            • 对b进行左旋。左旋后,为了保持红黑树特性,就需要把 b,c的颜色互换
        • CASE 2: 如果关注节点是a,它的兄弟节点c是黑色,并且节点c的左右子节点d,e都是黑色
          • 请添加图片描述

          • 操作策略

            • 将关注节点a的兄弟节点c的颜色变成红色
            • 从关注节点a中去掉一个黑色,这个时候节点a就是单纯的红色或者黑色
            • 给关注节点a的父节点b添加一个黑色,这个时候节点b就变成来"红-黑" 或者"黑 - 黑"
            • 关注节点从a变成其父节点b
            • 继续从四种情况中选择符合的规则来调整
          • 策略说明

            • 这个情况的处理思想是把"a中多余的一个黑色属性上移(往根节点方向)"
            • 假设a为"黑 + 黑"节点,将a由"黑 + 黑"节点变成"黑"节点,多余的一个"黑"属性,转移到父节点
            • b节点多出了一个黑属性(如b原先是"黑",则此时变成了"黑 + 黑";若b原先是红,则变成"红 + 黑")
            • 此时,所有经过a分支中黑色节点个数没变化
            • 因为经过c分支黑色节点个数+1了,需要把黑色数量-1。所以,要把 c设置为红色
        • CASE 3: 如果关注节点是a,它的兄弟节点c是黑色,c的左子节点d是红色,c的右子节点e是黑色
          • 请添加图片描述

          • 操作策略

            • 围绕关注节点a的兄弟节点c右旋
            • 节点c和节点d交换颜色
            • 关注节点不变
            • 跳转到CASE 4,继续调整
          • 策略说明

            • 主要是为了把CASE 3 转换成CASE 4
            • 对c进行右旋。为了保证右旋后仍然是红黑树,需要c和d交换颜色
            • 这个时候变成了平衡二叉树的单旋和双旋的情况,双旋的处理逻辑就是把双旋变成单旋(比如先右后左旋就是把树变成'左撇子')
        • CASE 4: 如果关注节点a的兄弟节点c是黑色,并且c的右子节点是红色的
          • 请添加图片描述

          • 操作策略

            • 围绕关注节点a的父节点b左旋
            • 将关注节点a的兄弟节点c的颜色,跟关注节点a的父节点b设置成相同的颜色
            • 将关注节点a父节点b的颜色设置为黑色
            • 从关键节点a中去掉一个黑色,节点a变成单纯的红色黑色
            • 将关注节点a的叔叔节点e设置为黑色
            • 调整结束
          • 策略说明

            • 目的:去除"黑-黑"/"红-黑"节点,变成单独的黑色节点
            • 左旋后为什么把 b设置成c的颜色?
              • 因为左旋后,把和b和d都是红色违反特征[3]
              • 如果都是黑色都违反特征[4]
            • 设置b为黑色,为了保证满足特征[4]
              • “同时经过根节点和a分支的黑色节点个数不变”
                • 只需要a丢弃多余的颜色。假设a的颜色"黑 + 黑",而左旋后"同时经过根节点和a分支的黑色节点"增加了1
                • 现在,只需要将a由"黑 + 黑"变成单独的"黑"节点
              • “同时经过根节点和d的分支的黑色节点不变”
                • 若要满足这个条件,只需要把b的原始颜色给c即可
                • 所以,最后算是对调了b和c的颜色
              • “同时经过根节点和e分支的黑色节点不变”
                • 在满足上一个条件下。要满足这个条件。把e设置成黑色即可
资料参考
  • 从2-3树到 红黑树
  • 清晰理解红黑树的演变—红黑的含义
  • 红黑树(一)之 原理和算法详细介绍
  • Red/Black Tree
  • 红黑树(四)之 C++的实现
  • 五分钟搞定什么是红黑树
  • [Data Structure] 数据结构中各种树
  • 教你初步了解红黑树
  • 经典算法研究系列:五、红黑树算法的实现与剖析
  • 一步一图一代码,一定要让你真正彻底明白红黑树
  • 从2-3-4树到红黑树(上)
  • 从2-3-4树到红黑树(中)
  • 从2-3-4树到红黑树(下) Java与C的实现

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/853847.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

阿里云香港服务器怎么样?

大家都知道阿里云是国内最受欢迎的云服务商,那么阿里云香港服务器究竟怎么样呢?和硅云的香港服务器用于做外贸网站等业务相比各有哪些优缺点呢? 阿里云和硅云在香港云服务领域有着广泛的应用和良好的口碑。然而,它们各自的特点和…

【V8引擎】 V8引擎如何运行JS的

文章目录 概要什么是V8引擎为什么需要V8引擎比较常见的javascript引起有哪些呢?V8引擎是如何工作的(V8引擎的解析过程)V8引擎的做了哪些优化 概要 本篇文章主要是讲V8引擎如何运行JS,对运行JS做了哪些优化 什么是V8引擎 V8 是一…

开发做前端好还是后端好?

目录 一、引言 二、两者的对比分析 技能要求和专业知识: 职责和工作内容: 项目类型和应用领域: 就业前景和市场需求: 三、技能转换和跨领域工作 评估当前技能: 确定目标领域: 掌握相关框架和库&a…

按键输入消抖

按键输入是人机对话不可缺少的一部分,对于消抖设计,一种是软件消抖,一种是硬件消抖。但在单片机电路设计中,采用电容消抖才是最佳的选择,其次才是定时器消抖。 1、按键输入采用软件消抖 1)、通过定时器方式定时读取按…

Vue3【二十一】Vue 路由模式(createWebHashHistory /createWebHistory )和RouterLink写法

Vue3【二十一】Vue 路由模式(createWebHashHistory /createWebHistory )和RouterLink写法 Vue3【二十一】Vue 路由模式和普通组件目录结构 createWebHistory history模式:url不带#号,需要后端做url适配 适合销售项目 利于seo crea…

CyberDAO:引领Web3时代的DAO社区文化

致力于Web3研究和孵化 CyberDAO自成立以来,致力于推动Web3研究和孵化,吸引了来自技术、资本、商业、应用与流量等领域的上千名热忱成员。我们为社区提供多元的Web3产品和商业机会,触达行业核心,助力成员捕获Web3.0时代的红利。 目…

C语言---------深入理解指针

目录 一、字符指针 二、指针数组: 三、数组指针: 1、定义: 2、&数组名和数组名区别: 3、数组指针的使用: 四、数组参数,指针参数: 1、一维数组传参: 2、二维数组传参&am…

模拟电子技术基础(二)--PN结

PN结的本质 芯片都是由硅晶体制成,单个硅原子最外层有带有4个电子 在纯硅当中这些电子会两两形成共价键,此时周围形成非常稳定的八电子结构 在一个回路中,灯泡不亮,不导通,因为电池无法吸引其中的电子离开&#xff0c…

Zombie Animations Set

僵尸动画合集,包括成对攻击/抓取、各种移动方式、爬行、击中反应、死亡动画等。 生产说明 动画总数:99(包括22个位置变化) 配对动画:36 攻击次数:6次 爬网:9 命中反应:6 空转:14 行程2 跑步次数:9次 短跑:2 匝数:3 步行次数:12次 免责声明 任何游戏玩法蓝图都不包…

力扣每日一题 6/16 字符串 + 随机一题 动态规划/数学

博客主页:誓则盟约系列专栏:IT竞赛 专栏关注博主,后期持续更新系列文章如果有错误感谢请大家批评指出,及时修改感谢大家点赞👍收藏⭐评论✍ 521.最长特殊序列 I【简单】 题目: 给你两个字符串 a 和 b&am…

【猫狗分类】Pytorch VGG16 实现猫狗分类4-开始训练

背景 现在,我们已经完成了,数据集的清洗,标签的制作,也把VGG16的模型建立好了。那接下来,我们应该把数据,放到我们搭建的vgg16的模型里面,让模型针对这些猫和狗的图片,去进行训练&a…

面试题 17.17. 多次搜索

链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 题解&#xff1a; class Solution { private:struct Trie {Trie() {end false;index -1;next.resize(26);}bool end;int index;std::vector<std::unique_ptr<Trie>> next;};void insert_trie(int in…

【CT】LeetCode手撕—88. 合并两个有序数组

目录 题目1- 思路2- 实现⭐88. 合并两个有序数组——题解思路 2- ACM实现 题目 原题连接&#xff1a;88. 合并两个有序数组 1- 思路 模式识别 模式1&#xff1a;两个有序数组合并 ——> 双指针模式2&#xff1a;返回结果填充到 nums1[mn] ——> 需要开辟新的数组空间 …

lxml库在爬虫领域的贡献及应用

重头戏lxml库里面的xpath 一段代码给各位开开胃 这段代码首先导入了lxml库中的etree模块&#xff0c;然后定义了一个包含HTML内容的字符串html。接着&#xff0c;我们使用etree.HTML()函数解析这个HTML字符串&#xff0c;得到一个表示整个HTML文档的树形结构。最后&#xff0c;…

qt 实现模拟实际物体带速度的移动(水平、垂直、斜角度)——————附带完整代码

文章目录 0 效果1 原理1.1 图片旋转1.2 物体带速度移动 2 完整实现2.1 将车辆按钮封装为一个类&#xff1a;2.2 调用方法 3 完整代码参考 0 效果 实现后的效果如下 可以显示属性&#xff08;继承自QToolButton&#xff09;: 鼠标悬浮显示文字 按钮显示文字 1 原理 类继承…

Folx软件安装教程及最新版下载

简介&#xff1a; Folx Pro是一款适合Mac的专业下载工具也是一款BT下载器&#xff0c;Folx中文版有一个支持Retina显示的现代界面&#xff0c;提供独特的系统排序、存储下载内容与预览下载文件。Folx中文官网提供Folx教程、激活码、下载。 安 装 包 获 取 地 址&#xff1a; …

远程连接管理服务SHH

1.了解服务端和客户端 服务端&#xff1a;提供服务 客户端&#xff1a;享受服务 思考: 我们通过网络是如何找到我们想要访问的服务的? IP(提供服务的服务器)Port(找到相应的服务) 2.了解端口号的设定 说明:端口号只有整数&#xff0c;范围是从0 到65535 1&#xff5e;2…

warning LNK4017: DESCRIPTION 语句不支持目标平台;已忽略

文章目录 warning LNK4017: DESCRIPTION 语句不支持目标平台&#xff1b;已忽略概述笔记备注END warning LNK4017: DESCRIPTION 语句不支持目标平台&#xff1b;已忽略 概述 基于ATL的COM DLL导出函数&#xff0c;无法用__declspec(dllexport)直接在函数上标记为导出函数。 只…

Scala网络编程:代理设置与Curl库应用实例

在网络编程的世界里&#xff0c;Scala以其强大的并发模型和函数式编程特性&#xff0c;成为了开发者的得力助手。然而&#xff0c;网络请求往往需要通过代理服务器进行&#xff0c;以满足企业安全策略或访问控制的需求。本文将深入探讨如何在Scala中使用Curl库进行网络编程&…

MySQL第三方图形化工具:DBeaver

操纵数据库的语言&#xff0c;基于功能划分为4类&#xff1a; 数据定义:DDL(Data Definition Language)库的创建删除、表的创建删除等 数据操纵:DML(Data ManipulationLanguage)新增数据、删除数据、修改数据等 数据控制:DCL(Data ControlLanguage)新增用户、删除用户、密码…