【数据结构】红黑树

文章目录

  • 红黑树
    • 1. 红黑树的概念
    • 2. 红黑树的性质
    • 3. 红黑树节点的定义
    • 4. 红黑树的结构
    • 5. 红黑树的插入操作

红黑树

1. 红黑树的概念

红黑树,是一种二叉搜索树,但在每个节点上增加一个存储位表示节点的颜色,可以是Red或者是Black。通过任何一条根到叶子的路径各个节点着色方式的限制。红黑树确保任何一条路径不会比其他路径长度多出两倍,所以是平衡的

axvp38hpvb-1688804357297.png

2. 红黑树的性质

  1. 每个节点不是红色就是黑色
  2. 根节点是黑色的
  3. 如果一个节点是红色的,它的两个孩子节点是黑色的
  4. 对于每个节点,从该节点到其所有后代叶节点的简单路径上,包含相同数目的黑色节点
  5. 每个叶子节点都是黑色的(此处的叶子节点表示空节点)

3. 红黑树节点的定义

enum Color {RED,BLACK
};template<class ValueType>
class RBTreeNode {
public:explicit RBTreeNode(const ValueType& data = ValueType(), Color color = RED):_left(nullptr),_right(nullptr),_parent(nullptr), _data(data), _color(color){}RBTreeNode<ValueType>* _left;RBTreeNode<ValueType>* _right;RBTreeNode<ValueType>* _parent;ValueType _data;Color _color;
};

在节点的定义当中,为什么将节点的默认颜色给为红色?

通过把新插入的节点默认为红色,可以较快地满足红黑树的性质,并且减少了插入操作时需要进行的旋转操作次数,提高了插入操作的效率。同时,红色节点相对于黑色节点来说,占用的存储空间更小,节省了内存空间。因此,在红黑树中,默认将节点的颜色给为红色

4. 红黑树的结构

红黑树当中增加了一个头结点,如下图所示

3d0f86b7oj-1688805648289.png

5. 红黑树的插入操作

红黑树是在二叉搜索树的基础上加平衡限制条件,因此红黑树插入可以分为两步:

  1. 按照二叉搜索树的规则插入新节点
  2. 检测新节点插入之后红黑树的性质是否改变

约定:cur表示当前节点、p父节点、g为祖父节点,u为叔叔节点

  • 情况一:cur为红色,p为红,g为红, u存在且为红
a39w74374f-1688808732294.png

注意:上图的数可以是一棵完整的树,也可能是一棵子树

黑色是可以连着出现,但是红色节点不行。

如果g是根节点,调整完成之后,需要将g改为黑色。如果g是子树,g一定有双亲,且g的双亲如果是红色,需要继续向上调整

dzy6udzeum-1688809039293.png

cur 和 p均为红,违反了性质三。将p和u改为黑,然后把g当做cur继续向上调整

  • 情况二:cur为红,p为红,g为黑色。u不存在/u存在且为黑

19g7wdylhu-1688809399289.png

u的情况有两种

  1. 如果u不存在,则cur一定是新插入的节点。如果cur不是新插入的节点,则cur和p则一定有一个节点颜色是黑色,就不满足性质四
  2. 如果u存在,一定是黑色,那么cur原来的颜色一定是黑色,现在看到红色的原因是在调整的过程中将cur节点的颜色改为红色

p为g的左孩子,cur为p的左孩子,进行右旋

p为g的右孩子,cur为p的右孩子,进行左旋

p、g变色–p变黑,g变红

  • 情况三:cur为红,p为红,g为黑u不存在/u存在且为黑
while (parent && parent->_col == RED)
{Node* grandfather = parent->_parent;if (grandfather->_left == parent){Node* uncle = grandfather->_right;// 情况1:u存在且为红,变色处理,并继续往上处理if (uncle && uncle->_col == RED){parent->_col = BLACK;uncle->_col = BLACK;grandfather->_col = RED;// 继续往上调整cur = grandfather;parent = cur->_parent;}else // 情况2+3:u不存在/u存在且为黑,旋转+变色{//     g//   p   u// c if (cur == parent->_left){RotateR(grandfather);parent->_col = BLACK;grandfather->_col = RED;}else{//     g//   p   u//     cRotateL(parent);RotateR(grandfather);cur->_col = BLACK;//parent->_col = RED;grandfather->_col = RED;}break;}}else // (grandfather->_right == parent){//    g//  u   p//        cNode* uncle = grandfather->_left;// 情况1:u存在且为红,变色处理,并继续往上处理if (uncle && uncle->_col == RED){parent->_col = BLACK;uncle->_col = BLACK;grandfather->_col = RED;// 继续往上调整cur = grandfather;parent = cur->_parent;}else // 情况2+3:u不存在/u存在且为黑,旋转+变色{//    g//  u   p//        cif (cur == parent->_right){RotateL(grandfather);grandfather->_col = RED;parent->_col = BLACK;}else{//    g//  u   p//    cRotateR(parent);RotateL(grandfather);cur->_col = BLACK;grandfather->_col = RED;}break;}}
}_root->_col = BLACK;return true;
}

因为红黑树只要求最长路径不超过最短路径的两倍。相对而言降低了插入和旋转的次数。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Docker】Docker的部署含服务和应用、多租环境、Linux内核的详细介绍

前言 Docker 是一个开源的应用容器引擎&#xff0c;让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux或Windows操作系统的机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。 &#x1f4d5;作者简介&#xff1a;热…

简化生活之让AI以指定格式输出

原文合集地址如下&#xff0c;有需要的朋友可以关注 本文地址 合集地址 今天京东也宣布即将发布了自己的大模型&#xff0c;那么使用AI大模型进行工作或者生活将是必不可少的步骤。 建立命令 AI大模型是一种生成式聊天对话模型&#xff0c;我们可以通过预先定义命令的方式…

HTML的Input(type)的属性都有哪些

&#x1f607;作者介绍&#xff1a;一个有梦想、有理想、有目标的&#xff0c;且渴望能够学有所成的追梦人。 &#x1f386;学习格言&#xff1a;不读书的人,思想就会停止。——狄德罗 ⛪️个人主页&#xff1a;进入博主主页 &#x1f33c;欢迎小伙伴们访问到博主的文章内容&am…

flutter开发实战-Running Gradle task ‘assembleDebug‘ 的解决方法

flutter开发实战-Running Gradle task ‘assembleDebug‘ 的解决方法 使用Android studio经常出现Running Gradle task ‘assembleDebug‘问题&#xff0c;记录一下解决方法。 一、在Android目录下更改build.gradle 将repositories中的google(), mavenCentral() repositori…

linux_driver_day10

作业1 题目&#xff1a; 使用驱动代码实现如下要求 应用程序通过阻塞的io模型来读取number变量的值 number是内核驱动中的一个变量 number的值随着按键按下而改变&#xff08;按键中断&#xff09; 例如 numbero 按下按键 number1&#xff0c;再次按下按键 number0 在按下按…

未跟踪的文件: (使用 “git add <文件>...“ 以包含要提交的内容)怎么移除这些内容

有时候我们常常修改一些内容 手动就是&#xff1a;rm -rf system/core/healthd/images/.png 怎么丢弃呢&#xff1f; git clean -f . 删除这种文件

【学会动态规划】三步问题(2)

目录 动态规划怎么学&#xff1f; 1. 题目解析 2. 算法原理 1. 状态表示 2. 状态转移方程 3. 初始化 4. 填表顺序 5. 返回值 3. 代码编写 写在最后&#xff1a; 动态规划怎么学&#xff1f; 学习一个算法没有捷径&#xff0c;更何况是学习动态规划&#xff0c; 跟我…

数据库应用:MySQL索引

目录 一、理论 1.MySQL三层逻辑架构 2.索引结构 3.MyISAM与InnoDB对比 4.sql优化 5.MySQL 索引 6.MySQL索引原理 二、实验 1.创建索引 三、总结 一、理论 1.MySQL三层逻辑架构 MySQL的存储引擎架构将查询处理与数据的存储/提取相分离。 MySQL的逻辑架构图如下&…

PostgreSQL技术内幕(九)libpq通信协议

libpq通信协议是基于TCP/IP 协议的一套消息通信协议&#xff0c;它允许 psql、JDBC、PgAdmin等客户端程序传递查询给PostgreSQL后端服务器&#xff0c;并接收返回查询的结果。 在这次的直播中&#xff0c;我们为大家介绍了libpq通信协议的实现原理和执行机制&#xff0c;以下内…

springboot项目实战-API接口限流

1.简介 对接口限流的目的是通过对并发访问/请求进行限速&#xff0c;或者对一个时间窗口内的请求进行限速来保护系统&#xff0c;一旦达到限制速率则可以拒绝服务、排队或等待、降级等处理。 1.1.为什么需要限流? 大量正常用户高频访问导致服务器宕机恶意用户高频访问导致服…

stm32(时钟和中断事件知识点)

一、复位和时钟控制&#xff08;RCC&#xff09; 复位 系统复位 当发生以下任一事件时&#xff0c;产生一个系统复位&#xff1a; 1. NRST引脚上的低电平(外部复位) 2. 窗口看门狗计数终止(WWDG复位) 3. 独立看门狗计数终止(IWDG复位) 4. 软件复位(SW复位) 5. 低功耗管…

MJ魔法AI逼真绘画

最近在玩MJ绘画&#xff0c;将一些经验分享给大家。 经验1&#xff1a;主体尽量放在前面 作图通用指令&#xff1a;主体描述词场景风格清晰度比例V5。MJ的逻辑是优先绘制前面的词&#xff0c;如果你的场景里面包含多个人或物。一定要把你希望在画面中出现的主体放在前面&#…