数据结构 - 学习笔记 - 红黑树

news2024/9/29 17:24:05

数据结构 - 学习笔记 - 红黑树

  • 定义
  • 简介
  • 知识点
    • 1. 结点属性
    • 2. 前驱、后继
    • 3. 旋转
  • 查找
  • 插入
    • 父结点为黑色
    • 父结点为红色
    • 1. 有4种情形只需要变色(对应234树4结点)
      • 1.1. 变色实现平衡
      • 1.2. 递归调整颜色
    • 2. 有4种情形需要旋转 + 变色(对应234树3结点)
  • 删除
    • 子结点,**黑色**,视兄弟颜色处理
      • 1. 兄弟为红色
        • 1.1. 找真兄弟(转换的另一种说法)
      • 2. 兄弟为**黑色**
        • 2.1. 兄弟有红色子节点
        • 2.2. 兄弟红色子节点
          • 2.2.1. 父结点为红色
          • 2.2.2. 父结点为**黑色**
    • 时间复杂度
  • 辅助脚本
  • 参考资料

定义

  1. 所有结点非 。(插入新结点默认色,然后再按需调整)
  2. 根结点 必需是 色。
  3. 叶结点 必需是 色。(叶结点是指最末端的空结点。通常在代码中直接用 null 表示,不会创建实际结点。)
  4. 结点的子结点必需是 。有两棵子树。(不能有连续的两个结点)
  5. 任意结点叶节点 经过的 结点数量相同。(别忘记叶结点也是黑色结点 )

简介

  1. 红黑树234树的一种实现,所以学习红黑树前,先看 红黑树前传——234树。
  2. 它是一种自平衡二叉查找树
    2.1. 二叉查找树左子树所有结点值都 <= 父,右子树所有结点值都 >= 父。
    2.2. 左右子树也都是二叉查找树
    2.3. 二叉查找树存在不平衡的情况,极端情况就是个链表
  3. AVL(平衡二叉查找树)相比,适当舍弃平衡,换取插入删除性能提升的同时,兼顾了查找效率。(本质上就是引入了红色结点的概念,它作为填充物,不计入树高,可有可无。因此简少了调平衡的工作量。)
  4. 因此红黑树中保障的是 结点的平衡, 结点作为维持平衡的填充物不影响平衡。
  5. 路径可以全是 结点。如:
  6. 路径可以两 夹一 。如:
  7. 插入删除打破平衡时,通过变色旋转实现再平衡。

在这里插入图片描述

知识点

1. 结点属性

颜色、键、左子结点、右子结点、父结点(特殊情况:结点没有结点)

2. 前驱、后继

  • 前驱结点:从子树中找最大的结点
  • 后继结点:从子树中找最小的结点

如果我们中序遍历一次,得到从小到大排列的所有元素,就能很直观的看出,前驱后继就是当前结点身边一前一后的两位,删除当前结点,用它们其中一个补位,是最合适的了。

中序遍历结果:[2, 3, 4, 5, 6, 7, 8]
当前结点:5
前驱:4     后继:6

3. 旋转

  • 旋转操作不会改变树中序遍历的顺序。
  • 旋转操作通过挪东墙补西墙来维护二叉树的平衡。
(对E进行)左旋(对S进行)右旋
在这里插入图片描述在这里插入图片描述
  • 总结一下几个结点的规律:
结点缩写左旋规律右旋规律
EEE.parent 更新为S
E.right更新为S.left
E.right 更新为 S
E.parent 更新为 S.parent
SSS.left 更新为 E
S.parent 更新为 E.parent
S.parent 更新为E
S.left更新为E.right
between E and SBESBES.parent 更新为 EBES.parent 更新为 S
less than ELE不受任何影响不受任何影响
greater than SGS不受任何影响不受任何影响
当前子树的父结点P如果当前是左子树,更新 P.left如果当前是右子树,更新 P.right
  • 伪代码
// 左旋
S = E.right;
BES = S.left;
E.right = BES;
BES.parent = E;
S.parent = E.parent; // E.parent == S.parent.parent
if(S.parent == null){ // S没爹,自己就是根
	S.颜色 = 黑色
}else if(E.parent.left == E){ // E 是父的左子
	E.parent.left = S;
}else{					      // E 是父的右子
	E.parent.right = S;
}
S.left = E;
E.parent = S;

查找

  1. 从根结点开始。
  2. 对比结点与查找目标,
    2.1. 目标值 = 当前结点:成功找到目标。
    2.2. 目标值 < 当前结点:递归查找左子树
    2.3. 目标值 > 当前结点:递归查找右子树

插入

红黑树插入共12种情况:父4种,父8种。

  1. 插入的新结点,默认都是红色结点。
  2. 插入位置的父结点为黑色。不影响平衡,共 4 种情况。直接插入即可。
    2.1. 父结点无子结点,插入左子结点。
    2.2. 父结点无子结点,插入右子结点。
    2.3. 父结点有红色右子,插入左子
    2.4. 父结点有红色左子,插入右子
  3. 插入位置的父结点为红色
    3.1. 对应234树3结点有4种: LL、LR、RR、RL
    3.2. 对应234树4结点有4种:祖父黑色,父叔伯都是红色

父结点为黑色

直接插入即可。
在这里插入图片描述

父结点为红色

1. 有4种情形只需要变色(对应234树4结点)

结点情况结点为红色红色叔伯结点。
在这里插入图片描述

1.1. 变色实现平衡

在这里插入图片描述

  1. 【红黑树】 插入新结点
  2. 【红黑树】 结点、叔伯结点变成黑色祖父结点变成红色
    2.1. 结点与祖父结点调换颜色:满足红结点子必的定义。同时对于插入新结点的这一路径来说黑结点数未发生变化。
    2.2. 叔伯结点变成黑色祖父结点原本作为公共的黑结点,挪给左路后,右路就少了一个黑结点。因此 叔伯要站出来变维持平衡。
  3. 【红黑树】 最后祖父结点更新为当前结点。
    3.1. 判断曾祖是否为红色。如果是,则需要向上递归调整颜色,一直到根。
    3.2. 如果是根,直接染

1.2. 递归调整颜色

插入新结点 1 后递归触发变色。
触发递归的原因曾祖结点是染红祖父结点染红后出现两个连续红色结点的情况,需要以祖父为当前结点继续进行变色处理。最终到达根结点直接染黑结束。
在这里插入图片描述

2. 有4种情形需要旋转 + 变色(对应234树3结点)

结点情况结点为红色红色叔伯结点。

虽然共有4种 情形,但其中 LR可以转为LLRL可以转为RR。总之就是有拐弯的,都是转为一条直线,再处理。
1.1. LR 左旋1次,转为 LL
1.2. LL 右旋1次 + 插入结点染黑、祖父结点染红,实现平衡。
2.1. RL 右旋1次,转为 LL
2.2. RR 左旋1次 + 插入结点染黑、祖父结点染红,实现平衡。

在这里插入图片描述

删除

删除可能发生在树中的任意位置。结点删除后,可能影响树的平衡,需要重新调整实现平衡。
在这里插入图片描述
根据将被删除的目标结点颜色子结点数量,需要分别处理:

-当前红色当前黑色
两个子结点同黑色1. 使用前驱后继结点内容替换当前结点。(颜色保持不变)
2. 再删除前驱后继结点。(转变成了对:子结点的删除)
一个子结点直接删除1. 删除当前结点。
2. 使用子结点填补当前位置,并将颜色设置为黑色
子结点直接删除1. 当前为根:直接删除。
2. 兄弟为红色:转为黑色再继续处理。
3. 兄弟为黑色:按兄弟有无红色子节点,分别处理。详情如下:

子结点,黑色,视兄弟颜色处理

1. 兄弟为红色

兄弟为红色:兄弟转为黑色再继续处理。转换方法:

  1. 兄弟结点调整为黑色
  2. 结点调整为红色
  3. 当前结点的结点,进行右旋

在这里插入图片描述

1.1. 找真兄弟(转换的另一种说法)

红色兄弟转黑兄弟。也可以理解为:只有黑色才是真兄弟,红色是塑料兄弟。所以我们要找到真兄弟再干活。
在这里插入图片描述

  1. 当前是子结点,就获取父亲子结点,判断颜色。如果是黑色,找到兄弟,完成任务。
  2. 结果发现是红色交换颜色。(不存在连续,所以父必然是个黑结点)
  3. 父结点为支点,左旋 一次。
  4. 现在取父结点右子结点,就是真兄弟了。(就是兄弟左子结点)

如果当前是子。同理往左边找就行了。

2. 兄弟为黑色

黑色是真兄弟,可算见到亲人了。可以开始真正的删除操作了。

2.1. 兄弟有红色子节点

借用兄弟子结点修复平衡。
在这里插入图片描述

2.2. 兄弟红色子节点

借助父结点来修复平衡

2.2.1. 父结点为红色
  1. 删除当前结点。
  2. 兄弟结点调整为红色
  3. 结点调整为黑色

在这里插入图片描述

2.2.2. 父结点为黑色
  1. 删除当前结点。
  2. 兄弟结点调整为红色
  3. 结点作为当前结点,继续处理:
    3.1. 兄弟调整为红色
    3.2. 如果红色结点染。否则递归重复第3步。

在这里插入图片描述

时间复杂度

操作复杂度
查找O(lgn)
插入O(lgn)
删除O(lgn)

辅助脚本

红黑树可视化演示

var sleep = (delaytime = 1000) => {
  return new Promise(resolve => setTimeout(resolve, delaytime))
}
async function delayDo(arr, callback = data=>console.log(`数据:${data}`), delaytime) {
    var len = arr.length;
    for (let i = 0; i <len  ; i++) {        
        await sleep(delaytime);
        callback(arr[i]);
    }c
};
// 获取文本框
var [insertTxt, deleteTxt, findTxt] = [...document.querySelectorAll("#AlgorithmSpecificControls [type=Text]")];
// 获取按钮
var [insertBtn, deleteBtn, findBtn] = [...document.querySelectorAll("#AlgorithmSpecificControls [type=Button]")];
var process = {
	insert: function insert(v){	insertTxt.value = v; insertBtn.click();	},
	del: function del(v){ deleteTxt.value = v; deleteBtn.click(); },
	find: function find(v){ findTxt.value = v; findBtn.click(); }
}
// 遍历数组,间隔 n 秒处理一个元素。
function main(arr = [...Array(10).keys()], cb = v=>console.log(v), delaytime=200){
	delaytime = delaytime<200 ? 200 : delaytime
    delayDo(arr, v => cb(v), delaytime);
}
// 插入元素,间隔 200 毫秒
main([...Array(20).keys()].map(v=>v+1), process.insert, 800);

参考资料

笑虾:数据结构 - 学习笔记 - 红黑树前传——234树

www.cs.usfca.edu:Red/Black Tree 数据结构可视化
Programiz:Red-Black Tree
Algorithmtutor:Red Black Trees (with implementation in C++, Java, and Python)

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

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

相关文章

[JavaWeb]CSS

目录1. CSS语法1.1 常用样式-字体颜色1.2 常用样式-边框border1.3 常用样式-字体样式1.4 常用样式-超链接去下划线1.5 常用样式-列表去除修饰2.CSS 使用三种方式2.1 在标签的 style 属性上设置 CSS 样式2.2 在head 标签中,使用style 标签来定义需要的CSS样式2.3 把 CSS 样式写成…

线程的几种状态转换

线程在一定条件下&#xff0c;状态会发生变化。线程一共有以下几种状态&#xff1a; 1、新建状态(New)&#xff1a;新创建了一个线程对象。 2、就绪状态(Runnable)&#xff1a;线程对象创建后&#xff0c;其他线程调用了该对象的start()方法。该状态的线程位于“可运行线程池…

【头歌】顺序栈的基本操作及应用

第1关&#xff1a;顺序栈的基本操作任务描述本关任务是实现顺序栈的基本操作函数&#xff0c;以实现判断栈是否为满、是否为空、求栈元素个数、进栈和出栈等功能。相关知识栈的基本概念栈是一种特殊的线性表&#xff0c;其特殊性体现在元素插入和删除运算上&#xff0c;它的插入…

Sentry SDK使用(Vue/Browser JS/Laravel)

本文介绍通过Vue/Browser JS/Laravel三个平台对接Sentry SDK。1.在vue中使用这是入门指引&#xff0c;为了了解更多&#xff0c;请查看完整文档。为了收集错误信息和采集性能数据&#xff0c;需要安装以下两个包&#xff1a;sentry/vue(Sentrys Vue SDK)sentry/tracing(instrum…

【网络安全】Wireshark过滤数据包分析TCP三次握手

利用Wireshark分析TCP三次握手和四次挥手一、安装Wireshark二、界面介绍1. 网卡类型2. 首页功能2.1 按钮界面2.2 数据包列表2.3 数据包详细信息列表3. Wireshark过滤器3.1 设置数据抓取选项3.2 显示过滤器3.3 过滤关系3.4 复合过滤表达式3.5 常见用显示过滤需求及其对应表达式3…

IDaaS 如何帮助中小微企业(SMB)赢得市场先机|身份云研究院

数字化的本质是生产关系、生产要素的重构&#xff0c;目的是通过数字化技术释放更多生产力。数据是数字化变革中最重要的生产要素&#xff0c;而开发者则是数字世界中最重要的劳动者。对于企业来说&#xff0c;如何将数据转化成企业重要的生产资料以及如何提升开发者的效率为企…

机器学习算法竞赛实战--2,问题建模

目录 一&#xff0c;赛题理解 1&#xff0c;赛题理解 2&#xff0c;数据理解&#xff1a; 3&#xff0c;评价指标&#xff08;分类和回归&#xff09; 思考练习 当参赛者拿到竞赛题目的时候&#xff0c;首先应该考虑的事情就是问题建模&#xff0c;同时完成基线模型的管道…

如何备考2023年高级网络规划设计师?

网络规划设计师是软考高级考试科目之一&#xff0c;也是比较难的科目&#xff0c;据官方数据统计网规每年的通过率很低&#xff0c;而且每年只有下半年11月份考一次&#xff0c;如果是直接裸考&#xff0c;估计很悬哦~ 但是你参加考试获得证书的过程就是一个学习网络规划系统知…

一文揭晓,我是如何在Linux中查找自如

未来已来&#xff0c;只是不均衡地分布在当下 大家好&#xff0c;我是菜农&#xff0c;欢迎来到我的频道。 本文共 2187字&#xff0c;预计阅读 10 分钟 用过 Linux 的小伙伴都知道&#xff0c;在Linux系统中包含着大量的文件&#xff0c;绝大部分情况下&#xff0c;我们都是…

react hooks 中使用 Echarts图表中遇到的问题及相关配置

前言 项目开发中&#xff0c;需要做一个报表功能&#xff0c;看了下UI图&#xff0c;初步定下使用 echarts&#xff0c;不过之前使用 echarts 都是在 Vue2 和 Vue3 框架下开发&#xff0c;第一次使用 react-hooks 开发 echarts&#xff0c;将流程及一些 相关配置 写个随笔记录…

没有开发经验的程序员,怎么快速学习进入工作?

今天在群里&#xff0c;Ace老师遇到一位没有开发经验的同学&#xff0c;他的情况是这样的。 问题 Ace老师&#xff1a; 有一些伙伴&#xff0c;我现在真的没有想到太好的方法去教他&#xff0c;我跟大家讲一下他目前的情况&#xff0c;你们有经验的来和他说说这样的情况应该怎…

操作系统权限提升(三)之Windows系统内核溢出漏洞提权

系列文章 操作系统权限提升(一)之操作系统权限介绍 操作系统权限提升(二)之常见提权的环境介绍 注&#xff1a;阅读本编文章前&#xff0c;请先阅读系列文章&#xff0c;以免造成看不懂的情况&#xff01;&#xff01;&#xff01; Windows系统内核溢出漏洞提权介绍 溢出提…

五、环境的搭建

1、配置用户信息 以下操作是用终端模拟器Cmder&#xff0c;这个工具比较便捷&#xff0c;比如需要粘贴&#xff0c;点击一下鼠标右键就粘贴了。如果不想下载这个工具&#xff0c;也可以在终端操作(打开终端快捷键&#xff1a;Win R&#xff0c;输入cmd)。 (1)查看git 打开C…

Recast-Detour看这里就够了!

目录一、 Recast生成(一) 概述1&#xff0e; 简介(二) 生成过程1&#xff0e; 体素化2&#xff0e; 区域3&#xff0e; 轮廓4&#xff0e; 生成凸多边形5&#xff0e; 详细三角形(三) 配置1&#xff0e; 可配置参数2&#xff0e; 数据结构(四) 项目应用1&#xff0e; CS体系方案…

2023最新前端面试题3(持续更新)

46、HTML语义化 HTML 语义化就是让页面内容结构化&#xff0c;它有如下优点 1、易于用户阅读&#xff0c;样式丢失的时候能让页面呈现清晰的结构。 2、有利于 SEO&#xff0c;搜索引警根据标签来确定上下文和各个关键字的权重。 3、方便其他设备解析&#xff0c;如盲人阅读器根…

【Pytorch项目实战】之迁移学习:特征提取、微调、特征提取+微调、雾霾清除

文章目录迁移学习&#xff08;Transfer Learning&#xff09;方法一&#xff1a;特征提取&#xff08;Feature Extraction&#xff09;方法二&#xff1a;微调&#xff08;Fine Tuning&#xff09;&#xff08;一&#xff09;实战&#xff1a;基于特征提取的迁移学习&#xff0…

2023第三方应用苹果电脑磁盘读写工具Tuxera NTFS

今天&#xff0c;小编要来分享的是Mac下一款实用的NTFS读写软件——Tuxera NTFS&#xff0c;我们都知道OS X默认是不支持NTFS格式写入的&#xff0c;对于很多使用U盘或移动硬盘写操作的朋友来说非常的不便。而Tuxera NTFS很好的解决了这个问题。小子这次带来的是2023版本。 Tu…

kali入侵电脑

kali入侵电脑 注意&#xff1a;本文仅用于教学目的 1 kali制作exe控制电脑&#xff08;msfvenom&#xff09; kali是黑客常用的系统&#xff0c;里面集成了很多的攻击软件&#xff0c;这里我给大家演示一种使用kali制作.exe文件来控制自己电脑的方式。 msfvenom a Metasploit s…

Vue2 和Vue 3的区别

Vue 2 和 Vue 3的区别 1.双向数据绑定原理不同 Vue2 的双向数据绑定是利用ES5的一个APIObject.definePropert() 对数据进行劫持&#xff0c;结合发布订阅模式的方式来实现的。 Vue3 中使用ES6的Proxy API对数据代理。 Vue3 使用数据代理的优势有以下几点&#xff1a;1&#x…

深圳MES系统如何助力注塑企业实现数字化发展

家用电器、电子产品、日用品、医疗保健、汽车零部件、新能源以及建筑、玩具等行业对注塑制品需求量日益增长。注塑企业提供的各式各样注塑产品已深入到经济生活的各个领域&#xff0c;为国家经济的各个部门包括轻工业和重工业提供关键的支持。 现状 现在注塑企业的注塑机工作…