面试必备的红黑树,这可能是最容易理解的一篇了!

2023-11-16

点击上方Java之间”,选择“置顶或者星标”

你关注的就是我关心的!

640?wx_fmt=jpeg

来源:linux内核

红黑树是一个平衡的二叉树,但不是一个完美的平衡二叉树。虽然我们希望一个所有查找都能在~lgN次比较内结束,但是这样在动态插入中保持树的完美平衡代价太高,所以,我们稍微放松逛一下限制,希望找到一个能在对数时间内完成查找的数据结构。这个时候,红黑树站了出来。

阅读以下需要了解普通二叉树的插入以及删除操作。

红黑树是在普通二叉树上,对没个节点添加一个颜色属性形成的,同时整个红黑二叉树需要同时满足一下五条性质

红黑树需要满足的五条性质:

性质一:节点是红色或者是黑色;

在树里面的节点不是红色的就是黑色的,没有其他颜色,要不怎么叫红黑树呢,是吧。

性质二:根节点是黑色;

根节点总是黑色的。它不能为红。

性质三:每个叶节点(NIL或空节点)是黑色;

这个可能有点理解困难,可以看图:

640?wx_fmt=jpeg


这个图片就是一个红黑树,NIL节点是个空节点,并且是黑色的。

性质四:每个红色节点的两个子节点都是黑色的(也就是说不存在两个连续的红色节点);

就是连续的两个节点不能是连续的红色,连续的两个节点的意思就是父节点与子节点不能是连续的红色。

性质五:从任一节点到其没个叶节点的所有路径都包含相同数目的黑色节点;

640?wx_fmt=jpeg


从上图可以看见相同数量的黑色节点有三个;

当我们进行插入或者删除操作时所作的一切操作都是为了调整树使之符合这五条性质。

下面我们先介绍两个基本操作,旋转。

旋转的目的是将节点多的一支出让节点给另一个节点少的一支,旋转操作在插入和删除操作中经常会用到,所以要熟记。

下面是左旋和右旋:

左旋:

640?wx_fmt=gif

右旋:

640?wx_fmt=gif

插入

下面讲讲插入

我们先明确一下各节点的叫法

640?wx_fmt=jpeg

因为要满足红黑树的这五条性质,如果我们插入的是黑色节点,那就违反了性质五,需要进行大规模调整,如果我们插入的是红色节点,那就只有在要插入节点的父节点也是红色的时候违反性质四或者是当插入的节点是根节点时,违反性质二,所以,我们把要插入的节点的颜色变成红色。

下面是可能遇到的插入的几种状况:

1、当插入的节点是根节点时,直接涂黑即可;

2、当要插入的节点的父节点是黑色的时候。

640?wx_fmt=jpeg

这个时候插入一个红色的节点并没有对这五个性质产生破坏。所以直接插入不用在进行调整操作。

3、如果要插入的节点的父节点是红色且父节点是祖父节点的左支的时候。

这个要分两种情况,一种是叔叔节点为黑的情况,一种是叔叔节点为红的情况。

当叔叔为黑时,也分为两种情况,一种是要插入的节点是父节点的左支,另一种是要插入的节点是父亲的右支。

我们先看一下当要插入的节点是父节点的左支的情况:

640?wx_fmt=jpeg

这个时候违反了性质四,我们就需要进行调整操作,使之符合性质四,我们可以通过对祖父节点进行右旋同时将祖父节点和父节点的颜色进行互换,这样就变成了:

640?wx_fmt=jpeg

经过这样的调整可以符合性质四并且不对其他性质产生破坏。

当插入的节点是父节点的右支的时候:

640?wx_fmt=jpeg

当要插入的节点是父节点的右支的时候,我们可以先对父节点进行左旋,变成如下:

640?wx_fmt=jpeg

如果我们把原先的父节点看做是新的要插入的节点,把原先要插入的节点看做是新的父节点,那就变成了当要插入的节点在父节点的左支的情况,对,是的,就是按照当要插入的节点在父节点的左支的情况进行旋转,旋转完之后变成如下:

640?wx_fmt=jpeg

4、如果要插入的节点的父节点是红色且父节点是祖父节点的右支的时候;

这个时候的情况跟情况3所表述的情况是一个镜像,将情况3的左和右互换一下就可以了。

5、如果要插入的节点的父节点是红色并且叔叔节点也为红色,如下:

640?wx_fmt=jpeg

这个时候,只需将父亲节点和叔叔节点涂黑,将祖父节点涂红。

以上就是插入的全部过程。

删除

首先你要了解普通二叉树的删除操作:

1、如果删除的是叶节点,可以直接删除;

2、如果被删除的元素有一个子节点,可以将子节点直接移到被删除元素的位置;

3、如果有两个子节点,这时候就可以把被删除元素的右支的最小节点(被删除元素右支的最左边的节点)和被删除元素互换,我们把被删除元素右支的最左边的节点称之为后继节点(后继元素),然后在根据情况1或者情况2进行操作。如图:

640?wx_fmt=jpeg

将被删除元素与其右支的最小元素互换,变成如下图所示:

640?wx_fmt=jpeg

然后再将被删除元素删除:

640?wx_fmt=jpeg

我们下面所称的被删除元素,皆是指已经互换之后的被删除元素。

加入颜色之后,被删除元素和后继元素互换只是值得互换,并不互换颜色,这个要注意。

下面开始讲一下红黑树删除的规则:

1、当被删除元素为红时,对五条性质没有什么影响,直接删除。

2、当被删除元素为黑且为根节点时,直接删除。

3、当被删除元素为黑,且有一个右子节点为红时,将右子节点涂黑放到被删除元素的位置,如图:

640?wx_fmt=jpeg

变成

640?wx_fmt=jpeg

4、当被删除元素为黑,且兄弟节点为黑,兄弟节点两个孩子也为黑,父节点为红,此时,交换兄弟节点与父节点的颜色;NIL元素是指每个叶节点都有两个空的,颜色为黑的NIL元素,需要他的时候就可以把它看成两个黑元素,不需要的时候可以忽视他。

如图:

640?wx_fmt=jpeg

变成:

640?wx_fmt=jpeg

5、当被删除元素为黑、并且为父节点的左支,且兄弟颜色为黑,兄弟的右支为红色,这个时候需要交换兄弟与父亲的颜色,并把父亲涂黑、兄弟的右支涂黑,并以父节点为中心左转。如图:

由:

640?wx_fmt=jpeg

变成:

640?wx_fmt=jpeg

6、当被删除元素为黑、并且为父节点的左支,且兄弟颜色为黑,兄弟的左支为红色,这个时候需要先把兄弟与兄弟的左子节点颜色互换,进行右转,然后就变成了规则5一样了,在按照规则5进行旋转。如图:

640?wx_fmt=jpeg

先兄弟与兄弟的左子节点颜色互换,进行右转,变成:

640?wx_fmt=jpeg

然后在按照规则5进行旋转,变成:

640?wx_fmt=jpeg

7、当被删除元素为黑且为父元素的右支时,跟情况5.情况6 互为镜像。

8、被删除元素为黑且兄弟节点为黑,兄弟节点的孩子为黑,父亲为黑,这个时候需要将兄弟节点变为红,再把父亲看做那个被删除的元素(只是看做,实际上不删除),看看父亲符和哪一条删除规则,进行处理变化如图:

由:

640?wx_fmt=jpeg

变成:

640?wx_fmt=jpeg

9、当被删除的元素为黑,且为父元素的左支,兄弟节点为红色的时候,需要交换兄弟节点与父亲结点的颜色,以父亲结点进行左旋,就变成了情况4,在按照情况四进行操作即可,变化如下:

由:

640?wx_fmt=jpeg

交换兄弟节点与父亲结点的颜色,以父亲结点进行左旋 变成:

640?wx_fmt=jpeg

在按照情况四进行操作,变成:

640?wx_fmt=jpeg

好了,删除的步骤也讲完,没有讲到的一点就是,在添加删除的时候,时刻要记得更改根元素的颜色为黑。

这里并没有语言实现,只是讲了一下红黑树的插入删除步骤,你可以根据步骤自己把红黑树实现。

点击这里,照着规则一步一步的构建一个红黑树吧。

最后

1、红黑树的实现其实是一个2、3、4树,只是将双节点或者三节点用红色进行了标示,如果你将红色节点放到和它父元素相同的高度,并把它和父元素看做是一个元素,你就会发现,变成了一个高度为lgN的二叉树,这个2.3.4树对红黑树很有启发意义。

2、上面的步骤其实可以不用死记硬背,是可以推导出来的,因为我们是把一个平衡但通过插入或者删除破坏了平衡的红黑树再次平衡,同过旋转让位,改变红黑颜色,使之符合那五条基本性质。比如遇到删除操作情况四的时候,我们可以把那个删除元素去除,发现左边比右边少一个黑元素,这个时候,怎么办,我们发现兄弟节点的子元素有一个红元素,操作这个不会影响那五条性质,所以我们通过变换颜色,旋转,即可让左右两边的的黑色数目一样。

3、旋转操作的目的是出让一个元素到另外的地方并且符合二叉树左小右大的性质,交换颜色的目的是为了保持红黑树的那五条性质。

4、要时刻记得 ,一切的操作都是为了保持那五条性质。

最后的最后,其实还有一种更为简单的红黑二叉树,这个简单的红黑二叉树实际上是一个2.3树,他只允许左节点为红节点,但是性能上肯定是不如这个红黑树。这个简单的红黑二叉树在《算法》第四版有介绍,掌握完之后再看这个简单的红黑二叉树,就会觉着简单 easy。

最后的最后的最后,一定要尝试着自己推导一下插入删除规则啊,不然经常忘,是睡一觉起来再看就有点懵逼的那种忘。


原文链接:

www.toutiao.com/i6668460505192989197/


最近热文阅读:

1、漫漫优化路,总会错几步(记一次接口优化)

2、浏览器缓存的这些知识点你都清楚吗?

3、版本帝!Java 12今天正式发布!

4、9个offer,12家公司,35场面试,从微软到谷歌,应届计算机毕业生的求职之路!

5、那天,我无意间瞟了眼程序员的桌面……

6、一次 Java 内存泄漏的排查

7、步步深入MySQL:架构->查询执行流程->SQL解析顺序!

8、让面试官颤抖的Tomcat系统架构系列!

640?wx_fmt=jpeg

关注公众号,你想要的Java都在这里

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

面试必备的红黑树,这可能是最容易理解的一篇了! 的相关文章

  • React Hooks:Effect无限回调踩坑

    场景 我的目的是通过Effect来模拟组件的componentDidMount 在渲染完成之后 通过setTimeout来处理操作 向keyIndex中push一个新的元素 并更新keyIndex 但是这个操作我确定只会执行一次 错误代码如
  • a和ajax跳转页面,ajax 页面跳转

    ajax 页面跳转 内容精选 换一换 面包屑组件 是项目中常用的一种组件 结构大致是 首页 菜单1 菜单2 菜单3 接入配置完成后 伙伴可以在能力开放页面配置伙伴平台回跳地址 以便于客户在完成订单支付后能返回到伙伴销售平台或者客户支付订单需
  • 适合下班后的副业,4个比较实际的副业兼职

    每一个上班族 都有一个发财的梦想 希望可以通过自己的努力 让领导看到自身价值 得到赏识 快速升职加薪 赚得盆满钵满 这样是不错 而且不少上班族单纯依靠工作就实现了这样的梦想 但是对于绝大部分普通人来说 还只存在于 想 如果现有的工作暂时没有
  • pdf注释上锁_如何在iPad上突出显示和注释PDF

    pdf注释上锁 Khamosh Pathak Khamosh Pathak The iPad is a great way to read PDFs but what if you want to highlight parts of it
  • STM32采用普通的IO口来测量PWM的频率

    STM32测量外部输入信号的频率的方法有很多 采用内部定时器输入捕获功能 采用普通的IO口设置外部中断 定时器的当时测量PWM信号的频率 这两种方式比较推荐使用第一种 比较使用内部的资源可以节省CPU资源的利用 当然当内部资源不够使用的时候
  • Unity LensFlares(镜头炫光)踩坑以及解决总结

    镜头光晕 Lens Flares 模拟相机镜头内的折射光线的效果 主要作用就是让太阳光 其他光源更加真实 Build in Build in管线中 可以直接添加Lens Flare组件即可获得效果 URP 2019 在Unity2019版本
  • 【mcuclub】CO2及TVOC检测-SGP30

    一 实物图 二 原理图 编号 名称 功能 1 VCC 电源正 2 GND 电源地 3 SDA 串行地址和数据输入 输出 4 SCL 串行时钟输入 三 简介 SGP30是一款单一芯片上具有多个传感元件的金属氧化物室内气体传感器 内部集成4个气
  • 电赛分几种_参加电赛需要具备哪些知识呢?

    本文转载自 微信公众号 47竞赛 ID gh 1814a7d91c55 经微信公众号授权转载 如需转载与原文作者联系 电赛需要准备哪些知识呢 先分析一下电赛的题目 你会发现 题目主要分为控制类 仪器仪表类 信号源类 电源类 放大器类 高频通
  • QT 布局,控件自适应大小 自动缩放 自动布局

    目录 前言 1 先来说简单的布局控件自适应 说明我们实现了自动布局 3 通过代码设置控件自动缩放重写resizeEvent 4 源码 https upload csdn net creation uploadResources 866208
  • 第1章 用物理模型进行高效的水模拟

    一 用物理模型进行高效的水模拟 一句话概括 基本网格的几何波动 动态法线贴图 1 1现状 1 快速傅里叶FFT在大中尺寸栅格取得逼真效果 并能适用于顶点shader和像素shader 2 能基于体素 Voxel 对简化的Navier Sto
  • 在培训班里学IT技术是否有用?和大家分享相关IT培训班里五大常见宣传手法、相关优势与实际效果

    目录 Introduction 引言 IT培训班常见宣传手法 培训班的优势 如何评判IT培训班的效果与质量 除IT培训班之外的学习渠道 总结 其它资料下载 Introduction 引言 随着信息技术的飞速发展 学习IT技术成为许多人追求职
  • win10搜索大文件

    直接在资源管理器的搜索框中敲 size gt 1G win 10计算机查找大文件 教你如何在Win10系统中查找大文件
  • WIN+R 实用大总结

    文章目录 cmd 与管理员cmd 打开网络共享中心 ncpa cpl 打开画画 mspaint 打开系统配置 msconfig 打开设备管理器 devmgmt msc 打开远程桌面连接 mstsc 任务管理器 taskmgr 系统属性 sy
  • Win10+vs2017 webrtc下载和编译

    现在使用webrtc的小伙伴越来越多 我也来凑凑热闹 第一步自然是下载源码 其实官网上面写的还是蛮详细的 只是环境搭建稍稍复杂了点 再加上国内不能访问google 所以简单的事情就变得复杂起来 我就按照官网上面的流程给大家简单介绍下 具体细
  • Flink Web UI 介绍

    一 提交flink任务到yarn flink run m yarn cluster yn 1 p 2 yjm 1024 ytm 1024 ynm FlinkOnYarnSession MemberLogInfoProducer d c co
  • 金蝶生成凭证模板_金蝶精斗云产品的优势

    1 金蝶精斗云产品免维护安装 产品免安装 免维护 免年结 自动升级 账号式授权加密 自动备份 会计归档 不需要固定的服务器 e64845f06572190e4634c2be37ab9ee9 png 2 金蝶精斗云系统凭证便捷生成 图片 PD
  • 反接保护电路:

    反接保护电路 通常我们的电子产品 为防止用户将正负极接反 会对接口做防反接保护 比如接口做成梯形或者开个缺口 反了不容易插进 但你真的永远不知道你的产品用户是萌妹纸还是暴力怪蜀黍 最终 这些防接反设计还是被突破了 被暴力插了进去 插进去了
  • uboot联网以及uboot重启问题

    一 配置uboot联网 虚拟机联网 配置uboot联网 1 配置uboot环境变量 setenv ipaddr 192 168 10 50 开发板ip地址 setenv ethaddr 00 04 9f 04 d2 35 mcu期间地址 多
  • ESP8266 CUT HERE FOR EXCEPTION DECODER解决办法

    串口log信息 CUT HERE FOR EXCEPTION DECODER Soft WDT reset gt gt gt stack gt gt gt ctx cont sp 3ffffd40 end 3fffffc0 offset 0
  • java使用多线程同时插入数据库数据例子

    今天自己在家准备面试内容 写了个java使用多线程往mysql数据库插入数据的例子 总结 不管数据库引擎是MYISAM还是InnoDB 情况都是 没有线程池的情况下就不说了 一直创建数据库连接一会就出错了 基本对于上万条的数据插入不可用 使

随机推荐

  • vue2的响应式

    结合源码分析一下vue的响应式 之前对于响应式 只是简单 很表面上的认识 知道vue的响应式主要通过Object defineProperty 方法来进行数据劫持以及发布者 订阅模式来实现的 但是如何进行数据劫持呢 发布订阅者模式又是什么呢
  • 安装pygame

    在学习了一个学期的python之后 我决定对pygame下手了 首先要安装pygame 对于一个计算机小白 安装的过程就比较的痛苦 但是怎么说 查阅了各方资料 好歹是安装完毕 预备条件 win10 python3 9 7 打开cmd win
  • 【vue2】按需引入多个组件的写法

    可以使用component标签 is 组件名 dialogTitle dialogTitle 和 rowInfo offlineRow 就是父给子传值的写法
  • 汽车雷达-综述

    目录 1 简介 2 发展史 3 技术参数 4 采用SIGe毫米波T R组件 5 汽车雷达中主要的信号处理单元 5 1 远程雷达 5 1 1 总体框图 5 1 2 FFT 5 1 3 DOA估计 5 1 3 1 和差测角 5 1 3 2 顺序
  • 多种排序算法(插入、二分法【查找、排序】、选择、冒泡、快速、希尔)

    多种排序算法 插入 二分法 查找 排序 选择 冒泡 快速 希尔 插入排序 function insertSort arr var len arr length for var i 1 i lt len i var key arr i var
  • 用户行为预测论文summay

    用户行为预测论文summary 1 论文名称 Modelingand Predicting Behavioral Dynamics on the Web 2 论文作者 KiraRadinskyz Krysta Svorey 3 主要内容 本
  • 论文阅读--Realtime Multi-Person 2D Pose Estimation using Part Affinity Fields

    多人姿态估计的挑战 1 人数 位置和尺寸的大小未知 2 人体之间的相互接触 遮挡造成干扰 3 复杂度随着实时人数的增加而提升 姿态估计方法 1 top down approaches 自顶向下 借助现有的用于单人姿势判断的技术 先检测人 然
  • 趣味算法:探索栈和队列的神秘之旅

    文章目录 前言 一 栈和队列 从历史到理论 二 栈和队列 实际例子和代码 1 栈在后缀表达式求解中的应用 2 队列在打印任务调度中的应用 三 栈和队列 更多的应用场景 四 栈和队列 如何选择 五 栈和队列的变体 六 性能分析 结语 前言 编
  • spring boot 统一JSON格式的接口返回结果

    前后端分离的项目开发前 会提前规定好数据返回格式 本文以JSON为例 第一步 定义好JavaBean package com yclouds myhelper web response import com fasterxml jackso
  • 输入商品数量和单价,计算商品总额。(C语言)

    代码 define CRT SECURE NO WARNINGS 1 include
  • 【PyTorch】使用 Mac GPUs (Apple silicon GPUs) 训练模型

    根据 PyTorch 官网的文章 Introducing Accelerated PyTorch Training on Mac1 从 PyTorch v1 12 release 开始支持使用 Apple silicon GPUs 加速训练
  • ML-熵、条件熵、信息增益

    通俗理解条件熵 特征选择之信息增益法 必看 系统介绍了熵 条件熵 信息增益的概念及推导 条件熵的计算 必看 知乎前三个回答都看一下 有关于熵 条件熵 信息增益的实践 我通过例子一步一步讲解这个概念 在决策树算法的学习过程中 信息增益是特征选
  • stm32实现网页服务器,STM32实现Web服务器

    实例简介 有例程及详细的讲解 适用于初学嵌入式WebServer的同学下载 实例截图 核心代码 ourdev 682501O2PDF8 10M以太网 WEB服务器 源码 PDF教程 以太网ENC28J60 pdf 以太网ENC28J60源码
  • KNN分类——matlab(转载)

    KNN分类 matlab 时间 2016 09 06 标签 matlab knn算法 算法 栏目 MATLAB 原文 http blog csdn net lwwangfang article details 52452429 adsbyg
  • elasticSearch 设置用户名密码 && 查询

    一 设置密码 1 需要在配置文件中开启x pack验证 修改config目录下面的elasticsearch yml文件 在里面添加如下内容 并重启 xpack security enabled true xpack license sel
  • SpringBoot集成RabbitMQ生产消费消息(简单实用版)

    概要 要使用RabbitMQ消息队列主要有两个步骤 一个是搭建RabbitMQ服务 需下载安装 二是代码添加依赖开始编码 一 安装RabbitMQ服务 以docker安装为例 其他安装方式自行百度 下载镜像 docker pull rabb
  • Java中的链表——LinkedList解析

    LinkedList类结构 LinkedList
  • TCP思维导图总结

    TCP 可靠性 为什么网络中会存在不可靠 根本原因就是距离太远 不可控因素太多 TCP因此就应运而生 是一种保证可靠性的协议 TCP协议格式 源 目的端口 表示数据从那个进程来 要到对端的那个进程去 32位序号 32位确认序号 分别代表TC
  • Authing 入选长城战略咨询《2023 中国潜在独角兽企业》报告

    2023 年 6 月 20 日 长城战略咨询 GEI 发布 2023 中国潜在独角兽企业研究 报告 Authing 作为国内首家身份云 IDaaS 厂商入选中国潜在独角兽企业榜单 独角兽企业指具有发展速度快 数量稀少 备受投资者青睐等属性的
  • 面试必备的红黑树,这可能是最容易理解的一篇了!

    点击上方 Java之间 选择 置顶或者星标 你关注的就是我关心的 来源 linux内核 红黑树是一个平衡的二叉树 但不是一个完美的平衡二叉树 虽然我们希望一个所有查找都能在 lgN次比较内结束 但是这样在动态插入中保持树的完美平衡代价太高