基本数据结构之红黑树

2023-10-31 13:50

本文主要是介绍基本数据结构之红黑树,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

红黑树

红黑树(Red-Black Tree,R-B Tree)是一种自平衡的二叉查找树。在红黑树的每个节点上都多出一个存储位表示节点的颜色,颜色只能是红(Red)或者黑(Black)。

是根据AVL树进化而来的,由于AVL树每次插入都需要动态调整,这需要大量的时间,因此出现了红黑树。

红黑树不会像AVL树那样,每次插入都需要动态调整。因此当数据经常变化的时候,红黑树的效率要比AVL树要高。

红黑树的特性

红黑树的特性如下。
◎ 每个节点或者是黑色的,或者是红色的。
◎ 根节点是黑色的。
◎ 每个叶子节点(NIL)都是黑色的。(叶子节点全是空指针)
◎ 如果一个节点是红色的,则它的子节点必须是黑色的。(不红红)
◎ 从一个节点到该节点的子孙节点的所有路径上都包含相同数量(黑路同)
的黑色节点。
具体的数据结构如图4-15所示:

在这里插入图片描述

红黑树的左旋

对a节点进行左旋,指将a节点的右子节点设为a节点的父节点,即将a节点变成一个左节点。因此左旋意味着被旋转的节点将变成一个左节点,具体流程如图 4-16所示。

在这里插入图片描述

大家注意看 d: 节点左旋之前挂在b上,左旋之后挂在节点a上,经历了一个重新挂枝的过程。

红黑树的右旋

对b节点进行右旋,指将b节点的左子节点设为b节点的父节点,即将b节点设为一个右节点。因此右旋意味着被旋转的节点将变成一个右节点,具体流程如图 4-17所示:

在这里插入图片描述

红黑树的添加

红黑树的添加分为 3步:①将红黑树看作一颗二叉查找树,并以二叉树的插入规则插入新节点;②将插入的节点涂为“红色”或“黑色”;③通过左旋、右旋或着色操作,使之重新成为一颗红黑树。根据被插入的节点的父节点的情况,可以将具体的插入分为3种情况来处理。
(1)如果被插入的节点是根节点,则直接把此节点涂为黑色的。
(2)如果被插入的节点的父节点是黑色的,则什么也不需要做,在节点插入后,仍然是红黑树。
(3)如果被插入的节点的父节点是红色的,则在被插入节点的父节点是红色的时,被插入节点一定存在非空祖父节点,即被插入节点也一定存在叔叔节点,即使叔叔节点(叔叔节点指当前节点的祖父节点的另一个子节点)为空,我们也视之为存在,空节点本身就是黑色节点。然后根据叔叔节点的颜色,在被插入节点的父节点是红色的
时,进一步分为3种情况来处理。
◎ 如果当前节点的父节点是红色的,当前节点的叔叔节点是红色的,则将父节点设为黑色的,将叔叔节点设为黑色的,将祖父节点设为红色的,将祖父节点设为当前节点。
◎ 如果当前节点的父节点是红色的,当前节点的叔叔节点是黑色的且当前节点是右节点,则将父节点设为当前节点,以新节点为支点左旋。
◎ 如果当前节点的父节点是红色的,当前节点的叔叔节点是黑色的且当前节点是左节点,则将父节点设为黑色的,将祖父节点设为红色的,以祖父节点为支点右旋。

红黑树的删除

红黑树的删除分为两步:①将红黑树看作一颗二叉查找树,根据二叉查找树的删除规则删除节点;②通过左旋、旋转、重新着色操作进行树修正,使之重新成为一棵红黑树,具体操作如下。
(1)将红黑树看作一颗二叉查找树,将节点删除。
◎ 如果被删除的节点没有子节点,那么直接将该节点删除。
◎ 如果被删除的节点只有一个子节点,那么直接删除该节点,并用该节点的唯一子节点替换该节点的位置。
◎ 如果被删除的节点有两个子节点,那么先找出该节点的替换节点,然后把替换节点的数据复制给该节点的数据,之后删除替换节点。
(2)通过左旋、旋转、重新着色操作进行树修正,使之重新成为一棵红黑树,因为红黑树在删除节点后可能会违背红黑树的特性,所以需要通过旋转和重新着色来修正该树,使之重新成为一棵红黑树:
①如果当前节点的子节点是“红+黑”节点,则直接把该节点设为黑色的;

②如果当前节点的子节点是“黑+黑”节点,且当前节点是根节点,则什么都不做;③如果当前节点的子节点是“黑+黑”节点,且当前节点不是根节点,则又可以分为以下几种情况进行处理。
◎ 如果当前节点的子节点是“黑+黑”节点,且当前节点的兄弟节点是红色的,则将当前节点的兄弟节点设置为黑色的,将父节点设置为红色的,对父节点进行左旋,重新设置当前节点的兄弟节点。
◎ 如果当前节点的子节点是“黑+黑”节点,且当前节点的兄弟节点是黑色的,兄弟节点的两个子节点也都是黑色的,则将当前节点的兄弟节点设置为红色的,设置当前节点的父节点为新节点。
◎ 如果当前节点的子节点是“黑+黑”节点,且当前节点的兄弟节点是黑色的,兄弟节点的左子节点是红色的且右子节点是黑色的,则将当前节点的左子节点设置为黑色的,将兄弟节点设置为红色的,对兄弟节点进行右旋,重新设置当前节点的兄弟节点。
◎ 如果当前节点的子节点是“黑+黑”节点,且当前节点的兄弟节点是黑色的,兄弟节点的右子节点是红色的且左子节点是任意颜色的,则将当前节点的父节点的颜色赋值给兄弟基点,将父节点设置为黑色的,将兄弟节点的右子节点设置为黑色的,对父节点进行左旋,设置当前节点为根节点。

总结

若红红,看叔节点脸色:
(1)红叔,爷叔父节点染色,爷变为新节点

(2)黑叔,此时需要旋转+染色体

旋转:

(1)若LL型,右旋;爷父换位并染色

(2)若RR型,左旋;爷父换位并染色

(3)若LR型,先左后右,爷儿换位并染色

(4)若RL型,先右后左,爷儿换位并染色

这篇关于基本数据结构之红黑树的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/315795

相关文章

C#连接SQL server数据库命令的基本步骤

《C#连接SQLserver数据库命令的基本步骤》文章讲解了连接SQLServer数据库的步骤,包括引入命名空间、构建连接字符串、使用SqlConnection和SqlCommand执行SQL操作,... 目录建议配合使用:如何下载和安装SQL server数据库-CSDN博客1. 引入必要的命名空间2.

Java中的数组与集合基本用法详解

《Java中的数组与集合基本用法详解》本文介绍了Java数组和集合框架的基础知识,数组部分涵盖了一维、二维及多维数组的声明、初始化、访问与遍历方法,以及Arrays类的常用操作,对Java数组与集合相... 目录一、Java数组基础1.1 数组结构概述1.2 一维数组1.2.1 声明与初始化1.2.2 访问

Go语言数据库编程GORM 的基本使用详解

《Go语言数据库编程GORM的基本使用详解》GORM是Go语言流行的ORM框架,封装database/sql,支持自动迁移、关联、事务等,提供CRUD、条件查询、钩子函数、日志等功能,简化数据库操作... 目录一、安装与初始化1. 安装 GORM 及数据库驱动2. 建立数据库连接二、定义模型结构体三、自动迁

ModelMapper基本使用和常见场景示例详解

《ModelMapper基本使用和常见场景示例详解》ModelMapper是Java对象映射库,支持自动映射、自定义规则、集合转换及高级配置(如匹配策略、转换器),可集成SpringBoot,减少样板... 目录1. 添加依赖2. 基本用法示例:简单对象映射3. 自定义映射规则4. 集合映射5. 高级配置匹

SQL BETWEEN 语句的基本用法详解

《SQLBETWEEN语句的基本用法详解》SQLBETWEEN语句是一个用于在SQL查询中指定查询条件的重要工具,它允许用户指定一个范围,用于筛选符合特定条件的记录,本文将详细介绍BETWEEN语... 目录概述BETWEEN 语句的基本用法BETWEEN 语句的示例示例 1:查询年龄在 20 到 30 岁

mysql中insert into的基本用法和一些示例

《mysql中insertinto的基本用法和一些示例》INSERTINTO用于向MySQL表插入新行,支持单行/多行及部分列插入,下面给大家介绍mysql中insertinto的基本用法和一些示例... 目录基本语法插入单行数据插入多行数据插入部分列的数据插入默认值注意事项在mysql中,INSERT I

mapstruct中的@Mapper注解的基本用法

《mapstruct中的@Mapper注解的基本用法》在MapStruct中,@Mapper注解是核心注解之一,用于标记一个接口或抽象类为MapStruct的映射器(Mapper),本文给大家介绍ma... 目录1. 基本用法2. 常用属性3. 高级用法4. 注意事项5. 总结6. 编译异常处理在MapSt

MyBatis ResultMap 的基本用法示例详解

《MyBatisResultMap的基本用法示例详解》在MyBatis中,resultMap用于定义数据库查询结果到Java对象属性的映射关系,本文给大家介绍MyBatisResultMap的基本... 目录MyBATis 中的 resultMap1. resultMap 的基本语法2. 简单的 resul

Java 枚举的基本使用方法及实际使用场景

《Java枚举的基本使用方法及实际使用场景》枚举是Java中一种特殊的类,用于定义一组固定的常量,枚举类型提供了更好的类型安全性和可读性,适用于需要定义一组有限且固定的值的场景,本文给大家介绍Jav... 目录一、什么是枚举?二、枚举的基本使用方法定义枚举三、实际使用场景代替常量状态机四、更多用法1.实现接

git stash命令基本用法详解

《gitstash命令基本用法详解》gitstash是Git中一个非常有用的命令,它可以临时保存当前工作区的修改,让你可以切换到其他分支或者处理其他任务,而不需要提交这些还未完成的修改,这篇文章主要... 目录一、基本用法1. 保存当前修改(包括暂存区和工作区的内容)2. 查看保存了哪些 stash3. 恢