数据结构:搜索二叉树 | 红黑树 | 验证是否为红黑树
文章目录
- 1.红黑树的概述
- 2.红黑树的性质
- 3.红黑树的代码实现
- 3.1.红黑树的节点定义
- 3.2.红黑树的插入操作
- 3.3.红黑树是否平衡
黑红树是一颗特殊的搜索二叉树,本文在前文的基础上,图解红黑树插入:前文 链接,完整对部分关键代码展示,完整的代码在gitee仓库中: 链接
文章中有错误的地方,欢迎大家指正!如果有帮助到你,也请多多点赞支持!
1.红黑树的概述
平衡二叉树要求左右子树的高度差的绝对值不超过1,所以平衡二叉树是高度平衡的,正是因为它要求严格控制高度差,在频繁的插入的删除的时候导致旋转次数过多带来了一定的性能消耗!
红黑树也是一颗特殊的搜索二叉树,任何一条从根到叶子的路径上各个结点由颜色(红黑)方式的限制,红黑树确保没有一条路径会比其他路径长出两倍(最长路径不会超过最短路径的两倍),它而是接近平衡的。红黑树没有严格要求高度的平衡,所以红黑树在总体的性能上会略优于平衡二叉树(AVL树)。
在现实的各种应用中都是使用红黑树的来充当数据结构,如:Java集合中的TreeMap,C++STL中Set、Map等都是使用红黑树而不是AVL树。可能在查找方面AVL树会由于红黑树,但是几十次的常数差别,在现代CPU(大概每秒几十亿次)来说完全不受影响,AVL树和红黑树查找的时间复杂度都是在一个等级上O(log_2(N)),红黑树在插入和删除会优于AVL树!
2.红黑树的性质
- 每个结点不是红色就是黑色
- 根节点必须是黑色的
- 如果一个节点是红色的,则它的两个孩子结点必须是是黑色的,(即:不会有两个连续的红节点)
- 对于每个结点,从该结点到其所有后代叶结点的简单路径上,均包含相同数目的黑色结点(即:每条路径上黑色的节点相同)
- 每个叶子结点都是黑色的(此处的叶子结点指的是空结点,即下图的NIL)
关于路径问题
上图有11条路径
为什么满足上面的性质,红黑树就能保证:其最长路径中节点个数不会超过最短路径节点个数的两倍
最短路径:全黑的路径 最长路径:一黑一红相间的路径
上面的图情况就是最大的(4个节点/2个节点 = 2倍)的情况!
3.红黑树的代码实现
3.1.红黑树的节点定义
enum color
{RED,BLACK
};template<class K, class V>
struct RBNode
{std::pair<K, V> _kv;RBNode<K, V>* _left;RBNode<K, V>* _right;RBNode<K, V>* _parent;color _color;RBNode(const std::pair<K, V> kv):_kv(kv), _left(nullptr), _right(nullptr), _parent(nullptr), _color(RED){}
};
3.2.红黑树的插入操作
第一大类情况:cur、parent为红,grandfather为黑,uncle存在且为红!
- 将parent和uncle都变为黑,grandfather变为红
- 但是grandfather,如果是根节点直接将其设为黑即可,
- 如果grandfather不为红,如下图:则将cur = grandfather继续重复步骤1和步骤2
**第二大类情况:**cur为红,parent为红,grandfather为黑,uncle不存在或uncle存在且为黑
单旋的情况:
- 下图是uncle不存在或uncle存在且为黑单旋的情况,通过节点的位置判断单旋:如条件是grandfather ->left = parent; parent->left = cur; 直线说明是单旋,都是左边说明右边高,要右单旋!
- 变色,grandfather变为红,parent变为黑色;可以看到,调整后的根据原来的grandfather是黑色,无论往上的祖先是何种颜色,都不会出现两个红色连一起的情况,不用往上调整了!
双旋的情况:
- 通过上面的例子可以知道,存在uncle且为黑和不存在uncle的处理结果是一样的!
- 通过下图的判断,是折线:grandfather ->left = parnt;parent->right =cur;通过平衡二叉树的插入操作的学习,可以知道,这种情况先左单旋,再右单旋!
- 变色:grandfather变为红,cur变为黑;可以看到,调整后的根据原来的grandfather是黑色,无论往上的祖先是何种颜色,都不会出现两个红色连一起的情况,不用往上调整了!
上面就是红黑树的**左子树的插入操作!右子树的插入99%是一样的!**可能没有99%,哈哈哈!但是是类似的操作!简单画个图:
第一大类情况:
第二大类情况:
单旋情况:
双旋情况:
bool insert(const std::pair<K, V>& kv)
{if (_root == nullptr){_root = new Node(kv);_root->_color = BLACK;return true;}Node* parent = nullptr;Node* cur = _root;while (cur){if (cur->_kv.first < kv.first){parent = cur;cur = cur->_right;}else if (cur->_kv.first > kv.first){parent = cur;cur = cur->_left;}else{return false;}}cur = new Node(kv);if (parent->_kv.first < kv.first){parent->_right = cur;}else{parent->_left = cur;}cur->_parent = parent;while (parent && parent->_color == RED){Node* grandfather = parent->_parent;// parent是左子树if (parent == grandfather->_left){Node* uncle = grandfather->_right;// 第一大类:uncle存在且为红if (uncle && uncle->_color == RED){// 改变颜色parent->_color = uncle->_color = BLACK;grandfather->_color = RED;// 修改条件,继续往上执行cur = grandfather;parent = cur->_parent;}else // 第二大类:uncle不存在或uncle存在且为黑{// 单旋情况if (cur == parent->_left){// 右单旋RotateRight(grandfather);// 改变颜色parent->_color = BLACK;grandfather->_color = RED;}else // 双旋情况{RotateLeft(parent);RotateRight(grandfather);cur->_color = BLACK;grandfather->_color = RED;}// 这种情况就不用重复调整,直接跳出循环break;}}else // parent是右子树{Node* uncle = grandfather->_left;if (uncle && uncle->_color == RED){parent->_color = uncle->_color= BLACK;grandfather->_color = RED;cur = grandfather;parent = cur->_parent;}else{if (cur == parent->_right){RotateLeft(grandfather);parent->_color = BLACK;grandfather->_color = RED;}else{RotateRight(parent);RotateLeft(grandfather);cur->_color = BLACK;grandfather->_color = RED;}break;}}}// 根绝对为黑色_root->_color = BLACK;return true;
}
3.3.红黑树是否平衡
根据每条路径的黑节点的个数相同判断!
bool isBanlan()
{// 如何判断是否为红黑树// 1.高度行不行? 不行! 2.能不能根据节点的个数不操作2倍的关系? 也不行// 3.那有什么是确定的?所有路径黑节点的个数相等!根据这个性质!Node* cur = _root;int checkNum = 0;while (cur){if(cur->_color == BLACK)checkNum++;cur = cur->_left;}return isBanlan(_root,checkNum,0);
}bool isBanlan(Node* root,int &checkNum,int blackNum)
{if (root == nullptr)return true;if (root->_color == BLACK){blackNum++;}if (root->_left == nullptr && root->_right == nullptr){return blackNum == checkNum ? true : false;}bool left = isBanlan(root->_left, checkNum, blackNum);bool right = isBanlan(root->_right, checkNum, blackNum);return left && right;
}
相关文章:

数据结构:搜索二叉树 | 红黑树 | 验证是否为红黑树
文章目录 1.红黑树的概述2.红黑树的性质3.红黑树的代码实现3.1.红黑树的节点定义3.2.红黑树的插入操作3.3.红黑树是否平衡 黑红树是一颗特殊的搜索二叉树,本文在前文的基础上,图解红黑树插入:前文 链接,完整对部分关键代码展示&a…...

数据结构顺序表
思维导图 练习 头文件 1 #ifndef __HEAD_H__2 #define __HEAD_H__3 4 5 #include <stdio.h>6 #include <string.h>7 #include <stdlib.h>8 9 10 #define MAXSIZE 711 typedef int datatype;12 enum13 {14 FLASE-1,15 SUCCESS16 };17 //定义顺序表&a…...

手把手教你优雅的安装虚拟机 Ubuntu —— 图文并茂
目录 Ubuntu 获取Vmware 安装新建虚拟机Ubuntu 安装虚拟机工具安装更多内容 本文教你如何优雅的在虚拟机中安装 Ubuntu,图文并茂、包教包会! Ubuntu 获取 Ubuntu 官网镜像下载速度较慢,建议从国内镜像网站下载,如网易、中科大、…...
源 “MySQL 5.7 Community Server“ 的 GPG 密钥已安装,但是不适用于此软件包。请检查源的公钥 URL 是否配置正确。
源 “MySQL 5.7 Community Server” 的 GPG 密钥已安装,但是不适用于此软件包。请检查源的公钥 URL 是否配置正确。 失败的软件包是:mysql-community-server-5.7.44-1.el7.x86_64 GPG 密钥配置为:file:///etc/pki/rpm-gpg/RPM-GPG-KEY-mysql…...
springboot核心有几层架构
Spring Boot核心有四层架构: 应用层:包含应用程序的入口点和控制器层。这层负责接收请求、处理业务逻辑,并返回响应结果。 服务层:包含业务逻辑的实现。这层负责处理各种业务逻辑,例如数据处理、事务管理等。 数据访…...

css3表格练习
1.效果图 2.html <div class"line"></div><h3>获奖名单</h3><!-- 表格 cellspacing内边距 cellpadding外边距--><table cellspacing"0" cellpadding"0" ><!-- thead表头 --><thead><tr>…...

项目实战——Qt实现FFmpeg音视频转码器
文章目录 前言一、移植 FFmpeg 相关文件二、绘制 ui 界面三、实现简单的转码四、功能优化1、控件布局及美化2、缩放界面3、实现拖拽4、解析文件5、开启独立线程6、开启定时器7、最终运行效果 五、附录六、资源自取 前言 本文记录使用 Qt 实现 FFmepg 音视频转码器项目的开发过…...

AI数字人-数字人视频创作数字人直播效果媲美真人
在科技的不断革新下,数字人技术正日益融入到人们的生活中。近年来,随着AI技术的进一步发展,数字人视频创作领域出现了一种新的创新方式——AI数字人。数字人视频通过AI算法生成虚拟主播,其外貌、动作、语音等方面可与真实人类媲美…...

初识C语言·动态内存开辟
1 为什么要有动态内存开辟 int a 10; int arr[10] { 0 }; 上述定义了一个整型,开辟了4个字节,定义了一个整型数组,开辟了40个字节,但是是固定开辟的,面对灵活多变的实际问题的时候可能就有点鸡肋,这种开…...

机器学习 | 利用Pandas进入高级数据分析领域
目录 初识Pandas Pandas数据结构 基本数据操作 DataFrame运算 文件读取与存储 高级数据处理 初识Pandas Pandas是2008年WesMcKinney开发出的库,专门用于数据挖掘的开源python库,以Numpy为基础,借力Numpy模块在计算方面性能高的优势&am…...
三、计算机理论-计算机网络-物理层,数据通信的理论基础,物理传输媒体、编码与传输技术及传输系统
物理层概述 物理层为数据链路层提供了一条在物理的传输媒体上传送和接受比特流的能力。物理层提供信道的物理连接,主要任务可以描述为确定与传输媒体的接口有关的一些特性:机械特性、电气特性、功能特性、过程特性 数据通信的理论基础 数据通信的意义 主…...

ERROR Failed to get response from https://registry.npm.taobao.org/ 错误的解决
这个问题最近才出现的。可能跟淘宝镜像的证书到期有关。 解决方式一:更新淘宝镜像(本人测试无效,但建议尝试) 虽然无效,但感觉是有很大关系的。还是设置一下比较好。 淘宝镜像的地址(registry.npm.taobao…...
overflow产生的滚动条样式设置
修改overflow产生的滚动条样式,主要可以通过如下三个伪元素设置: 1)-webkit-scrollbar:设置水平滚动条的高度,垂直滚动的宽度 2)-webkit-scrollbar-thumb:设置滚动条里面的滑块样式 3)-webkit-scrollbar-track&…...
Ubuntu环境vscode配置Log4cplus库
1、下载源码 http://sourceforge.net/projects/log4cplus/ 2、安装 例如我下载的是2.0.8版本压缩包,需要解压缩 log4cplus-2.0.8.7z安装解压工具: apt install p7zip-full解压: 7z x log4cplus-2.0.8.7z -r -o/home/配置及编译安装&#x…...
vue中,使用file-saver导出文件,下载Excel文件、下载图片、下载文本
vue中,使用file-saver导出文件,下载Excel文件、下载图片、下载文本 1、基本介绍 npm地址:file-saver - npm 2、安装 # Basic Node.JS installation npm install file-saver --save bower install file-saver# Additional typescript defin…...
【VUE】v-if 和 v-show 大详解(多角度分析+面试简答版)
多角度分析+面试简答版 一、`v-if` 和 `v-show` 的区别之多角度分析控制手段:编译过程:编译条件:性能消耗:总结使用场景二、 `v-if`、`v-show`、`display:none` 和`visibility: hidden` 的区别三、简洁版回答:`v-show` 与 `v-if` 比较一、v-if 和 v-show 的区别之多角度分…...
mac intel jdk安装与配置
jdk地址下载 https://www.oracle.com/java/technologies/downloads/ https://repo.huaweicloud.com/java/jdk/8u201-b09/ 安装后 下载完成之后打开终端 注意如果是第一次配置环境变量需要创建.bash_profile文件。(注意:touch后面有空格) to…...

Backtrader 文档学习-Bracket Orders
Backtrader 文档学习-Bracket Orders 1. 概述 组合订单类型是一个非常宽泛的订单类别,只要brokder支持的订单类型都可以, 包括(Market, Limit, Close, Stop, StopLimit, StopTrail, StopTrailLimit, OCO)。 该功能用于回测,交互broker Brac…...

Python编程 从入门到实践(项目二:数据可视化)
本篇为实践项目二:数据可视化。 配合文章python编程入门学习,代码附文末。 项目二:数据可视化 1.生成数据1.1 安装Matplotlib1.2 绘制简单的折线图1.2.1 修改标签文字和线条粗细1.2.2 校正图形1.2.3 使用内置样式1.2.4 使用scatter()绘制散点…...

Linux版本下载Centos操作
目录 一、Centos7 二、下载Centos7镜像 三、下载Centos7 买了个硬件安装裸机(一堆硬件) 把安装盘放到虚拟机里面,给机器加电 配置设置 编辑 网络配置 开启网络功能 四、安装linux客户端 Xshell是什么 Xshell使用(连接…...
<6>-MySQL表的增删查改
目录 一,create(创建表) 二,retrieve(查询表) 1,select列 2,where条件 三,update(更新表) 四,delete(删除表…...
k8s从入门到放弃之Ingress七层负载
k8s从入门到放弃之Ingress七层负载 在Kubernetes(简称K8s)中,Ingress是一个API对象,它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress,你可…...

Python:操作 Excel 折叠
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...
在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:
在 HarmonyOS 应用开发中,手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力,既支持点击、长按、拖拽等基础单一手势的精细控制,也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档,…...

Docker 运行 Kafka 带 SASL 认证教程
Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明:server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...

家政维修平台实战20:权限设计
目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系,主要是分成几个表,用户表我们是记录用户的基础信息,包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题,不同的角色…...
多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验
一、多模态商品数据接口的技术架构 (一)多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如,当用户上传一张“蓝色连衣裙”的图片时,接口可自动提取图像中的颜色(RGB值&…...

P3 QT项目----记事本(3.8)
3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...

Android15默认授权浮窗权限
我们经常有那种需求,客户需要定制的apk集成在ROM中,并且默认授予其【显示在其他应用的上层】权限,也就是我们常说的浮窗权限,那么我们就可以通过以下方法在wms、ams等系统服务的systemReady()方法中调用即可实现预置应用默认授权浮…...
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南 在数字化营销时代,邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天,我们将深入解析邮件打开率、网站可用性、页面参与时…...