【数据结构与算法】实现红黑树

news2024/11/25 14:24:18

文章目录

      • 一、红黑树的五条规则
      • 二、红黑树的三种变换
        • 2.1.变色
        • 2.2.左旋转
        • 2.3.右旋转
      • 三、红黑树的插入操作
        • 3.1.情况1
        • 3.2.情况2
        • 3.3.情况3
        • 3.4.情况4
        • 3.5.情况5
        • 3.6.案例
          • 插入10
          • 插入9
          • 插入8
          • 插入7
          • 插入6
          • 插入5
          • 插入4
          • 插入3
          • 插入2
          • 插入1

一、红黑树的五条规则

红黑树除了符合二叉搜索树的基本规则外,还添加了以下特性:

  • 规则1:节点是红色或黑色的;
  • 规则2:根节点是黑色的;
  • 规则3:每个叶子节点都是黑色的空节点(NIL节点);
  • 规则4:每个红色节点的两个子节点都是黑色的(从每个叶子到根的所有路径上不可能有两个连续的红色节点);
  • 规则5:从任一节点到其每个叶子节点的所有路径都包含相同数目的黑色节点;

在这里插入图片描述

红黑树的相对平衡

前面5条规则的约束确保了以下红黑树的关键特性:

  • 根到叶子节点最长路径,不会超过最短路径两倍
  • 结果就是这棵树基本是平衡的;
  • 虽然没有做到绝对的平衡,但是可以保证在最坏的情况下,该树依然是高效的;

为什么可以做到最长路径不超过最短路径的两倍呢?

  • 性质4决定了路径上不能有两个相连的红色节点;
  • 所以,最长路径一定是红色节点和黑色节点交替而成的;
  • 由于根节点和叶子节点都是黑色的,最短路径可能都是黑色节点,并且最长路径中一定是黑色节点多于红色节点;
  • 性质5决定了所有路径上都有相同数目的黑色节点;
  • 这就表明了没有路径能多于其他任何路径两倍长。

二、红黑树的三种变换

插入一个新节点时,有可能树不再平衡,可以通过三种方式的变换使树保持平衡:

  • 变色
  • 左旋转
  • 右旋转
2.1.变色

为了重新符合红黑树的规则,需要把红色节点变为黑色,或者把黑色节点变为红色

插入的新节点通常都是红色节点

  • 当插入的节点为红色的时候,大多数情况不违反红黑树的任何规则;
  • 插入黑色节点,必然会导致一条路径上多了一个黑色节点,这是很难调整的;
  • 红色节点虽然可能导致红红相连的情况,但是这种情况可以通过颜色调换和旋转来调整;
2.2.左旋转

以节点X为根逆时针旋转二叉搜索树,使得父节点原来的位置被自己的右子节点替代,左子节点的位置被父节点替代;

在这里插入图片描述

详解:

如上图所示,左旋转之后:

  • 节点X取代了节点a原来的位置;
  • 节点Y取代了节点X原来的位置;
  • 节点X的左子树 a 仍然是节点X的左子树(这里X的左子树只有一个节点,有多个节点时同样适用,以下同理);
  • 节点Y的右子树 c 仍然是节点Y的右子树
  • 节点Y的左子树 b 向左平移成为了节点X的右子树

除此之外,二叉搜索树左旋转之后仍为二叉搜索树:

在这里插入图片描述

2.3.右旋转

以节点X为根顺时针旋转二叉搜索树,使得父节点原来的位置被自己的左子节点替代,右子节点的位置被父节点替代;

在这里插入图片描述

详解:

如上图所示,右旋转之后:

  • 节点X取代了节点a原来的位置;
  • 节点Y取代了节点X原来的位置;
  • 节点X的右子树 a 仍然是节点X的右子树(这里X的右子树虽然只有一个节点,但是多个节点时同样适用,以下同理);
  • 节点Y的左子树 b 仍然是节点Y的左子树
  • 节点Y的右子树 **c 向**右平移成为了节点X的左子树

除此之外,二叉搜索树右旋转之后仍为二叉搜索树:

在这里插入图片描述

三、红黑树的插入操作

首先需要明确,在保证满足红黑树5条规则的情况下,新插入的节点必然是红色节点

为了方便说明,规定以下四个节点:新插入节点为N(Node),N的父节点为P(Parent),P的兄弟节点为U(Uncle),U的父节点为G(Grandpa),如下图所示:

在这里插入图片描述

3.1.情况1

当插入的新节点N位于树的根上时,没有父节点。

这种情况下,只需要将红色节点变为黑色节点即可满足规则2 。

在这里插入图片描述

3.2.情况2

新界点N的父节点P为黑色节点,此时不需要任何变化。

此时既满足规则4也满足规则5。尽管新节点是红色的,但是新节点N有两个黑色节点NIL,所以通向它的路径上黑色节点的个数依然相等,因此满足规则5 。

在这里插入图片描述

3.3.情况3

节点P为红色,节点U也为红色,此时节点G必为黑色,即父红叔红祖黑

在这种情况下需要:

  • 先将父节点P变为黑色;
  • 再将叔叔节点U变为黑色;
  • 最后将祖父节点G变为红色;

即变为父黑叔黑祖红,如下图所示:

在这里插入图片描述

可能出现的问题:

  • N的祖父节点G的父节点也可能是红色,这就违反了规则4,此时可以通过递归调整节点颜色;
  • 当递归调整到根节点时就需要旋转了,如下图节点A和节点B所示,具体情况后面会介绍;

在这里插入图片描述

3.4.情况4

节点P是红色节点,节点U是黑色节点,并且节点N为节点P的左子节点,此时节点G一定是黑色节点,即父红叔黑祖黑

在这种情况下需要:

  • 先变色:将父节点P变为黑色,将祖父节点G变为红色;
  • 后旋转:以祖父节点G为根进行右旋转;

在这里插入图片描述

3.5.情况5

节点P是红色节点,节点U是黑色节点,并且节点N为节点P的右子节点,此时节点G一定是黑色节点,即父红叔黑祖黑

在这种情况下需要:

  • 先以节点P为根进行左旋转,旋转后如图b所示;
  • 随后将红色节点P黑色节点B看成一个整体的红色节点N1,将新插入的红色节点N看成红色节点P1 如图c所示。此时整体就转换为了情况4。

在这里插入图片描述

接着可以按照情况4进行处理:

  • 先变色:将N1节点的父节点P1变为黑色,将祖父节点G变为红色;
  • 后旋转:以祖父节点G为根进行右旋转,旋转后如图 e 所示;
  • 最后将节点N1和P1变换回来,完成节点N的插入,如图 f 所示;

在这里插入图片描述

3.6.案例

在二叉树中依次插入节点:10,9,8,7,6,5,4,3,2,1 。

如果直接采用普通的二叉搜索树,节点全部插入后是这样的:

在这里插入图片描述

是一个严重的不平衡树,相当于一个链表,不能体现出二叉搜索树的高效率。而按照红黑树的五条规则插入节点就能最大程度保证搜索二叉树是一棵平衡树。以下为过程详解:为了方便解释省略了部分红黑树的叶子节点(NIL)

插入10

符合情况1

  • 插入节点10;
  • 将节点10的颜色变为黑色;

在这里插入图片描述

插入9

符合情况2

  • 不需要任何变化;

在这里插入图片描述

插入8

快速判断属于情况3还是情况4的方法:

从新插入的节点N出发,按图示箭头经过的四个节点,若为红红黑红3个红色节点则为情况3,若为红红黑黑两个红色节点则为情况4;

在这里插入图片描述

符合情况4

  • 父节点9变成黑,祖父节点10变为红;
  • 以祖父节点为根进行右旋转;

在这里插入图片描述

插入7

符合情况3

  • 父节点8和叔节点10变为黑,祖父节点9变为红;
  • 此时会出现问题:不符合规则2,即根节点不为黑,此时可以把以9为根节点的二叉搜索树当作一个整体作为一个新插入的节点N,而此时又符合情况1,只需要把9变回黑色即可。

在这里插入图片描述

插入6

符合情况4

  • 父节点7变为黑,祖父节点8变为红;
  • 以祖父节点8为根进行右旋转;

在这里插入图片描述

插入5

符合情况3

  • 父节点6和叔节点8变为黑,祖父节点7变为红;

在这里插入图片描述

插入4

符合情况4

  • 父节点5变为黑,祖父节点6变为红;
  • 以祖父节点6为根进行右旋转;

在这里插入图片描述

插入3

第一次变换:符合情况3

  • 父节点4和叔节点6变为黑,祖父节点5变为红;

变换之后发现5和7为相连的两个红色节点,于是把以5为根的整个子树看成一个新插入的节点N1,再进行第二次变换。

在这里插入图片描述

第二次变换:符合情况4

  • 父节点7变为黑,祖父节点9变为红;
  • 以祖父节点9为根进行右旋转;

在这里插入图片描述

最后复原N1得到变换后的红黑树:

在这里插入图片描述

插入2

符合情况4

  • 父节点3变为黑,祖父节点4变为红;
  • 以祖父节点4为根进行右旋转;

在这里插入图片描述

插入1

第一次变换:符合情况3

  • 父节点2和叔节点4变为黑,祖父节点3变为红;

变换之后发现3和5为相连的两个红色节点,于是把以3为根的整个子树看成一个新插入的节点N1,再进行第二次变换。

在这里插入图片描述

第二次变换:符合情况3

  • 父节点5和叔节点9变为黑,祖父节点7变为红;即由图 b -> 图 c 。

变换之后发现根节点7为红色不符合规则2,所以把以7为根节点的红黑树看成一个新插入的节点N2,再进行第三次变换。

第三次变换:符合情况1

  • 直接将根节点7变为黑色即可。

在这里插入图片描述

由此,完成了1~10节点的插入,虽然没有遇到情况5,不过情况5经过左旋转的操作便可转换为情况4,原理一样。如下图所示,将这棵红黑树的叶子节点NIL补全之后,经检验满足红黑树的五条规则,并且基本属于平衡树,效率较高。

在这里插入图片描述

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

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

相关文章

使用WebyogSQLyog使用数据库

数据库 实现数据持久化到本地: 使用完整的管理系统统一管理, 数据库(DateBase): 为了方便数据存储和管理(增删改查),将数据按照特定的规则存储起来 安装WebyogSQLyog -- 创建数…

探索低代码的潜力、挑战与未来展望

低代码开发作为一种新兴的开发方式,正在逐渐改变着传统的编程模式,低代码使得开发者无需编写大量的代码即可快速构建各种应用程序。然而,低代码也引发了一系列争议,有人称赞其为提升效率的利器,也有人担忧其可能带来的…

【Spring教程22】Spring框架实战:Spring事务角色与 Spring事务属性、事务传播行为代码示例详解

目录 1.Spring事务角色1.1 未开启Spring事务之前:1.2 开启Spring的事务管理后2 Spring事务属性2.1 事务配置2.2 转账业务追加日志案例2.2.1 需求分析2.2.2 环境准备 2.3 事务传播行为2.3.1.修改logService改变事务的传播行为2.3.2 事务传播行为的可选值 欢迎大家回到《 Java教…

【EXCEL】规划求解

题目: s1:设置EXCEL加载项(第一次使用):开发工具–>EXCEL加载项–>勾选“规划求解加载项”–>确定 s2:填入公式(等号左边) s3:数据–>规划求解 s4:得出结果 总结:这玩意…

0基础学java-day15(泛型)

一、泛型 1 泛型的理解和好处 1.1 看一个需求 【不小心加入其它类型,会导致出现类型转换异常】 package com.hspedu.generic;import java.util.ArrayList;/*** author 林然* version 1.0*/ public class Generic01 {SuppressWarnings("all")public st…

NSSCTF web刷题记录7

文章目录 [SDCTF 2022]CURL Up and Read [SDCTF 2022]CURL Up and Read 考点:SSRF 打开题目发现是curl命令,提示填入url 尝试http://www.baidu.com,成功跳转 将url的字符串拿去解码,得到json格式数据 读取下环境变量&#xff0c…

【算法集训】基础数据结构:三、链表

链表就是将所有数据都用一个链子串起来,其中链表也有多种形式,包含单向链表、双向链表等; 现在毕竟还是基础阶段,就先学习单链表吧; 链表用头结点head表示一整个链表,每个链表的节点包含当前节点的值val和下…

社交媒体图像识别与情感分析

社交媒体图像识别与情感分析是当前人工智能领域的一个研究热点。通过对社交媒体上大量的图像和文本数据进行深度学习和情感分析,可以提取出图像中的情感信息,从而为社交媒体用户提供更加个性化和精准的内容推荐和服务。 在社交媒体图像识别方面&#xff…

LabVIEW与Tektronix示波器实现电源测试自动化

LabVIEW与Tektronix示波器实现电源测试自动化 在现代电子测试与测量领域,自动化测试系统的构建是提高效率和精确度的关键。本案例介绍了如何利用LabVIEW软件结合Tektronix MDO MSO DPO2000/3000/4000系列示波器,开发一个自动化测试项目。该项目旨在自动…

C#结合JavaScript实现多文件上传

目录 需求 引入 关键代码 操作界面 ​JavaScript包程序 服务端 ashx 程序 服务端上传后处理程序 小结 需求 在许多应用场景里,多文件上传是一项比较实用的功能。实际应用中,多文件上传可以考虑如下需求: 1、对上传文件的类型、大小…

《微信小程序开发从入门到实战》学习四十五

4.4 云函数 云函数是开发者提前定义好的、保存在云端并且将在云端运行的JS函数。 开发者先定义好云函数,再使用微信开发工具将云函数上传到云空间,在云开发控制台中可看到已经上传的云函数。 云函数运行在云端Node.js环境中。 小程序端通过wx.cloud.…

使用阿里巴巴同步工具DataX实现Mysql与ElasticSearch数据同步

一、Linux环境要求 二、准备工作 2.1 Linux安装jdk 2.2 linux安装python 2.3 下载DataX: 三、DataX压缩包导入,解压缩 四、编写同步Job 五、执行Job 六、定时更新 6.1 创建定时任务 6.2 提交定时任务 6.3 查看定时任务 七、增量更新思路 一、Linux环境要…

内外网文件传输中的4大风险,你都知道吗?

一般来说,企业实施内外网隔离的原因主要就是两个:外因和内因。外因就是因为政策法规要求,这个主要是面向一些特定行业的,比如党政机关、金融、医疗、能源等行业,受这方面监管和要求的会比较多。内因就是为了自身的数据…

C++面试宝典第4题:合并链表

题目 有一个链表,其节点声明如下: struct TNode {int nData;struct TNode *pNext;TNode(int x) : nData(x), pNext(NULL) {} }; 现给定两个按升序排列的单链表pA和pB,请编写一个函数,实现这两个单链表的合并。合并后,…

架构设计系列之基础:初探软件架构设计

11 月开始突发奇想,想把自己在公司内部做的技术培训、平时的技术总结等等的内容分享出来,于是就开通了一个 Wechat 订阅号(灸哥漫谈),开始同步发送内容。 今天(12 月 10 日)也同步在 CSDN 上开通…

银行数字化转型导师坚鹏:兴业生活APP运营之道

基于招商银行案例研究的兴业生活APP运营之道培训圆满结束 ——线上引流平台流量经营与变现 兴业银行股份有限公司(简称“兴业银行”)成立于1988年8月,2022年总资产9.27万亿元,是经国务院、中国人民银行批准成立的首批股份制商业银…

Truffle的基础语法与js测试语法

truffle编译 truffle compiletruffle部署 truffle migratetruffle测试 使用test文件夹下的所有文件测试 truffle test使用单个文件 测试 truffle test 文件所在位置

实现Django Models的数据mock

目录 一、创建测试数据 二、使用随机数据 三、使用第三方库生成数据 四、编写测试用例 五、总结 在 Django 中,Model 是用于定义数据库表的结构的类。有时候,我们需要在测试或者开发过程中,模拟 Model 的数据,而不是直接从数…

Python 数据库操作SQL基础

文章目录 SQL 基础数据库和表的创建数据的插入、查询、更新和删除索引、连接和子查询 Python 中的数据库操作关于Python技术储备一、Python所有方向的学习路线二、Python基础学习视频三、精品Python学习书籍四、Python工具包项目源码合集①Python工具包②Python实战案例③Pytho…

Bluejay--控制多旋翼无刷电机的数字 ESC 固件

前言 Bluejay中文意思是冠蓝鸦,一种雀形目鸦科冠蓝鸦属的鸟类。在这里是用于控制多旋翼无刷电机的数字 ESC 固件。 基于BLHeli_S修订版 16.7 Bluejay 的目标是成为 BLHeli_S 的开源继承者,通过 Busy Bee MCU 对 ESC 进行多项改进。 特点 数字信号协议&…