红黑树

2-3-4树

JAVA技术交流群:737698533

定义

  1. 所有的叶子节点都拥有相同的深度
  2. 节点只能是2-节点,3-节点,或者4-节点
  3. 2节点 包含一个元素的节点,有两个子节点
  4. 3节点 包含两个元素的节点,有三个子节点
  5. 4节点 包含三个元素的节点,有四个子节点
  6. 所有节点都有至少两个子节点或没有子节点

来解释一下性质和一些定义

  1. 任意一个叶子节点(也就是没有子节点的节点)到根节点的距离一致
  2. 一个节点中可能包括1,2,3个元素,有2,3,4,个子节点,具体可以看下面的图
  3. 一个节点要么有至少两个子节点,要么没有节点

关于子节点如何定义的

  • 2节点 左子树所有元素小于key1,右子树所有元素大于key1
  • 3节点 左子树所有元素小于key1,中间子树所有元素大key1小于key2,右子树大于key2
  • 4节点 左子树所有元素小于key1,第二个子树所有元素大于key1小于key2,第三个子树所有元素大于key2小于key3,右子树所有元素大于key3

红黑树

为什么要提到234树呢,因为234树和红黑树是完全等价的,在程序中实现234树比较繁琐,所以使用了红黑树来代替

来看234树的添加操作

红黑树

添加如果出现需要分裂的情况,分裂出的元素首先进行和父级合并,如果父级已经是4节点那么将父级分裂,递归操作

234树的生长全部都是从叶子节点进行生长的,从叶子节点进行分裂向上延伸

红黑树

性质

  1. 每个节点要么红色,要么黑色
  2. 根节点是黑色
  3. 每个子节点 (NIL) 是黑色
  4. 每个红色节点的两个子节点一定是黑色
  5. 任意一节点到每个叶子节点的路径都包含数量相同的黑节点

解释一下性质

性质4和性质5说一下

如果一个红色节点那么它的两个子节点必须为黑色,包括nil节点,也就是说不能有两个红色节点相连

任意一个叶子节点或没有子节点的节点到根节点经过的黑色节点数量都一致,不懂下面再解释

叶子节点 : 标记为NIL,为虚拟节点,颜色必须为黑色,234中叶子节点为没有子节点的节点,而红黑树的叶子节点是虚拟的节点

234树和红黑树对比

红黑树

3节点的两种形态如果红色在左边就叫做左倾,红色在右边就叫做右倾

将234树进行转换为红黑树操作

右倾

红黑树

左倾

红黑树

现在来看一下几个没有子节点的节点下面其实都有两个NIL节点我们可以任意从一个nil节点出发,到6根节点,所经过的黑色节点个数是一样的,一般情况下NIL节点是不画出来的,但是不代表不存在

红黑树操作

变色:节点的颜色由黑变红或者由红变黑

左旋:以某个节点作为旋转点,其右子节点变为旋转节点的父节点,右子节点的左子节点变为旋转节点的右子节点,左子节点保持不变。

右旋:以某个节点作为旋转点,其左子节点变为旋转节点的父节点,左子节点的右子节点变为旋转节点的左子节点,右子节点保持不变

看图!

右旋操作

红黑树

左旋操作

红黑树

新增节点

对比234树进行添加

红黑树所有添加的节点默认都为红色

1 添加一个根节点

红黑树

添加第一个默认为红色的节点,发现与红黑树性质”根节点必须为黑色”冲突,我们将5变色为黑色即可,完成添加操作

2 添加一个节点,与2节点合并

红黑树

3 添加一个节点,与3节点合并

红黑树

根据234树转红黑树的两种状态导致添加时可能会出现两个红色节点相连的情况

左倾通过选转和变色可以变成右倾的状态,反之亦然

4 添加一个节点和4节点合并

红黑树

我们回到3和4,其中有需要调整的树

对于3里面的两种情况,看234树和红黑树的对比,4节点的红黑树形态是 上面黑色节点左右两边各一个红色节点,而现在是三个元素一条线,上面黑色节点,下面两个红色,我们已经知道它的最终形态是什么样子,只需要进行调整即可

红黑树

而对于上面的添加还有一种情况需要旋转两次,解决思路就是变换为上面的情况,然后按照上面的步骤完成

红黑树

而4里面的情况,进行变色即可

红黑树

如果经过变色爷爷节点变色为红色,假设不是根节点的话,与上面的其他节点发生冲突,我们把变色的爷爷节点当做新增的节点进行操作

如果爷爷节点的父亲节点和叔叔节点都为红色则继续按照上面的操作进行调整,如果叔叔节点不是红色则需要进行其他调整

例如下图,如果4的叔叔节点为红色,那么直接根节点变黑(先变红发现是根节点然后变黑)即可,如果叔叔节点为黑色,那么就需要进行旋转变色操作

红黑树

红黑树在线演示网站

删除节点

前驱节点和后继节点

删除一个节点肯定有人要替代被删除节点的位置,可以选择前驱节点或后继节点

前驱节点 : 小于当前节点的最大节点

后继节点 : 大于当前节点的最小节点

例如 下面图的6节点,前驱节点就是5,后继节点就是9

红黑树

除非左子树或右子树只有一个节点

寻找前驱节点就是寻找左子树的第一个节点的右儿子,一直往右找直到找到没有右子节点的节点

寻找后驱节点就是寻找右子树的第一个节点的左儿子,一直往左找直到找到没有左子节点的节点

删除一个节点可以理解为删除它的替换节点

为什么这么说呢,如果使用代码实现红黑树,一个节点至少有3个指针,左孩子指针,右孩子指针,父亲指针,节点中假设就存储一个值,那么移除原来的节点替换为新的节点需要移动:左右孩子指针,父指针,替换的左右孩子指针,左右孩子的父指针………

而我们将替换的节点的值赋值给需要删除的节点,还是上面那个图,假如我们删除10,使用后继节点11来替代,我们只需要将11的值赋值给10,然后删除11节点即可,也就是说只需要修改两个指针,11的父指针和12的左孩子指针即可完成

而在234树中,删除的永远都是叶子节点,可以看上面的图,前驱节点和后继节点用于都是在最底层

那么我们删除的情况从是否有孩子来看就只有两种

  1. 删除没有孩子的节点
  2. 删除有一个孩子的节点

为什么没有2个孩子的情况呢?如果删除一个节点来寻找它的替换节点,那么要么是前驱或后继,而这两个节点的条件是一直寻找左边孩子或右边孩子,如果一个节点有两个孩子,那么它肯定不是一个前驱或后继节点

红黑树

红黑树

后继节点同理,如果一个前驱节点或后继节点有两个子节点,那么它一定不是前驱节点或后继节点

前驱或后继节点从叶子节点开始的层数不会大于2

那还有个疑问,会不会出现下面这种情况,10的后继节点12这都3层了,不是说不会大于2吗

红黑树

这种情况存在吗?现在都知道红黑树是234树转换来的,那么234树中会出现一个节点只有一个孩子的情况吗?

234树的生长都是从叶子节点进行分裂的,也就是说除了叶子节点,就是说最少的子节点也就是两个,最多4个,不可能出现上图的情况,两个子节点的节点为2-节点,2节点除了第一次添加为根节点或叶子节点以外,任何2-节点都会连接两个子节点,而两个子节点肯定是2,3,4节点其中之一,转换红黑树不可能出现上图情况,可以回去看看234树转换红黑树对应图

那么下面开始进行删除

先在234树上进行删除

红黑树

可以直接进行删除的有4,11,13,其中4和5比较特殊,如果进行的是右倾操作,那么可以直接删除5

在234树删除操作中3-节点和4-节点是可以自己搞定的,例如删除4或5, 11或12或13,随便删除一个都不影响234树的性质

而在红黑树中删除只能删除234树对应的3-节点和4节点中红色节点,这几个节点可以直接删除,不需要任何额外操作

在红黑树中删除5只需要将4替换掉5,然后进行变色即可,红黑树的性质依然保持

删除

情况1,自己能搞定,对应234树当前要的删除3-节点或4-节点

  1. 叶子节点 例如是234树中的红色叶子节点或红黑树中没有子节点的红色节点直接删除 例如上图的红黑树中4,11,13节点,可以直接删除
  2. 有一个子节点 使用子节点来替代,如果需要进行变色 例如上图的红黑树中5节点,删除后4节点替代自己,然后变黑色,而12节点可以找左儿子或右儿子都可以替换自己

情况2 自己搞不定,需要兄弟节点和父亲节点帮忙

兄弟节点为3-节点的情况

红黑树

例如现在想要删除5,这时候就需要兄弟节点和父节点帮忙

首先将5删除,之后需要从兄弟节点拿来一个节点来弥补空缺,但是兄弟节点都比6大,如果直接放入无论是234树还是红黑树都会违反性质,234 : 3-节点的左子树元素全部小于key1 ,红黑树: 任何一个节点左边都是小于当前节点

这时我们把父亲节点用来弥补删除的空缺

红黑树

之后兄弟节点去弥补父节点的空缺

红黑树

那么回到红黑树呢?

红黑树

为什么会出现这种情况呢?我们回想一下234树转换红黑树的图,在234树中一个3-节点可能出现左倾或右倾的情况

上面是6在上面10在下面的情况,我们换成相反的情况来看看

红黑树

这时5的兄弟节点就和234树中的一样了,234树的3-节点转换为红黑树的两种情况都可以通过左旋变色或右旋变色进行变化

例如上图,我们6和8节点进行右旋,就会变成上面第二张图,而上面的第二张图6节点和8节点进行左旋又会变成上面的这张图

有没有发现一个问题呢,当红黑树5节点的兄弟节点为黑色时也就是说明它的兄弟节点和234树中5节点的兄弟节点一致

也就是说如果它的兄弟节点为红色,需要先进行旋转变色才能进行删除,而6和8变色在234树上等于没动,因为234树根本就没有颜色,只是为了方便对比红黑树添加的颜色

上面的图还有一种情况,就是3-节点7和8位置反的,8在上面7在下面,而替代需要兄弟节点中最小的元素来替代,如果出现这种情况需要先将7和8进行旋转换色,成为上面的情况,然后再进行替换

红黑树

再来看兄弟节点为4-节点的情况

红黑树

还是删除5节点,离它最近的兄弟节点是个4-节点

兄弟节点为4-节点的删除

只画需要修改的地方,先来看234树

红黑树

红黑树

红黑树

还有一种方法

红黑树

而对应红黑树就比较简单了

红黑树

最后关于变色为什么不是8和9变成黑色,因为红黑树必须保证每个叶子节点到根节点经过黑色节点个数相同,同时保证没有两个红色节点相连,如果是8和9变成黑色,为了第一条那么6和7必须变为红色,而变成红色就违反了第二条,上面的删除第一种操作最后的变色同理,如果7和9为黑色,那么从9的叶子节点出发将会比从7的叶子节点多一个黑色节点,违反了红黑树的性质

看个动图加深记忆

红黑树

这里使用的是第二种删除方式,因为可以少旋转一次

情况3,自己解决不了,兄弟节点也帮助不了(兄弟节点也没有子节点)

红黑树

如果父亲不是红色节点呢?没有办法补偿失去的黑色节点?那么就需要往上面将父节点的兄弟节点变为红色,来弥补爷爷节点的黑色平衡,然后将爷爷节点的父节点变黑,但是,如果爷爷节点的父节点也是黑色,那么就需要递归往上进行操作,知道找到父节点不为黑色的节点

进行上面操作后再根据删除节点的父节点,把父节点当做要删除的节点(并不真正删除),根据上面情况进行调整

本文仅个人理解,如果有不对的地方欢迎评论指出或私信,谢谢٩(๑>◡

Original: https://www.cnblogs.com/sunankang/p/14309507.html
Author: Jame!
Title: 红黑树

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/622114/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 【MySQL】笔记(2)— 部分 DQL 语句;条件查询;排序;分组函数;单行处理函数;group by ,having ;

    1.简单的查询语句(DQL): select 字段名1,字段名2,字段名3,…. from 表名; 注意:1、任何一条sql语句都以”;”结尾;…

    数据库 2023年5月24日
    0105
  • docker部署redis集群

    docker部署redis集群 1.0 安装环境 1.1 安装Centos7 Docker官方建议在Ubuntu中安装,因为Docker是基于Ubuntu发布的,而且一般Docke…

    数据库 2023年6月9日
    086
  • 我的JAVA面试题备忘录

    以下是我收集的一些问题,有的是网上摘录的,有的是自己参加面试被问到的,有的是工作或学习时遇到的,等等。 为什么要记录这些呢? 一方面,我相信,这样做对我自己的技术提升是有帮助的。在…

    数据库 2023年6月6日
    058
  • 常用函数封装汇总

    常用函数封装 获取某日期若干个工作日后的日期 * 参数: * time: [String] 给&#x5B9…

    数据库 2023年6月11日
    0110
  • B树-删除

    B树系列文章 1. B树-介绍 2. B树-查找 3. B树-插入 4. B树-删除 删除 根据B树的以下两个特性 每一个非叶子结点(除根结点)最少有 ⌈ m/2⌉ 个子结点 有k…

    数据库 2023年6月14日
    073
  • java基础

    java基础知识图解 软件开发 软件开发 软件,即一系列按照特定顺序组织的计算机数据和指令的集合。有系统软件和应用软件之分。 人机交互方式 图形化界面(Graphical User…

    数据库 2023年6月16日
    067
  • 3000帧动画图解MySQL为什么需要binlog、redo log和undo log

    全文建立在MySQL的存储引擎为InnoDB的基础上 先看一条SQL如何入库的: 这是一条很简单的更新SQL,从MySQL服务端接收到SQL到落盘,先后经过了MySQL Serve…

    数据库 2023年6月16日
    0123
  • 第07章 MySQL单行函数

    第07章 MySQL单行函数 1. 函数的理解 1.1 什么是函数 函数在计算机语言的使用中贯穿始终,函数的作用是什么呢?它可以把我们经常使用的代码封装起来,需要的时候直接调用即可…

    数据库 2023年5月24日
    070
  • MySQL InnoDB缓存

    1. 背景 对于各种用户数据、索引数据等各种数据都是需要持久化存储到磁盘,然后以”页”为单位进行读写。 相对于直接读写缓存,磁盘IO的成本相当高昂。 对于读…

    数据库 2023年6月14日
    0150
  • 2022蓝帽杯初赛wp(取证)

    战果 取证全解 misc出了1个 解其他题就像在坐牢 有那么一点思路,但不是完全有 手机取证_1 解压并打开阅读器,搜索627604C2-C586-48C1-AA16-FF33C3…

    数据库 2023年6月11日
    0100
  • MySQL启动过程详解二:核心模块启动 init_server_components()

    mysqld_main() 函数中,init_server_components() 函数负责MySQL核心模块的启动,包括mdl系统,Innodb存储引擎的启动等等: mdl子系…

    数据库 2023年6月9日
    091
  • 【Kubernetes系列】Kubernetes相关概念介绍

    Pod 是可以在 Kubernetes 中创建和管理的、最小的可部署的计算单元。是一组(一个或多个) 容器; 这些容器共享存储、网络、以及怎样运行这些容器的声明。 Pod 中的内容…

    数据库 2023年6月6日
    083
  • 如何制作验证码

    推导步骤1:在img标签的src属性里放上验证码的请求路径 补充1.img的src属&amp…

    数据库 2023年6月14日
    086
  • 什么是前缀索引?

    一、什么是前缀索引? 所谓前缀索引,说白了就是对文本的前几个字符建立索引( 具体是几个字符在建立索引时去指定),比如以产品名称的前 10 位来建索引,这样建立起来的索引更小,查询效…

    数据库 2023年6月14日
    0106
  • 容器化 | 使用 Alpine 构建 Redis 镜像

    上一期我们介绍了几种常见的构建镜像方式,并给出了功能对比、决策树等作为选型参考。本期我们将演示如何使用 Alpine 构建一个 Redis 镜像。 Alpine 系统使用 apk …

    数据库 2023年5月24日
    097
  • 【数据库】– 15个小技巧,拿捏SQL优化 【转载】

    前言 sql优化是一个大家都比较关注的热门话题,无论你在面试,还是工作中,都很有可能会遇到。 如果某天你负责的某个线上接口,出现了性能问题,需要做优化。那么你首先想到的很有可能是优…

    数据库 2023年6月6日
    0113
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球