红黑树-RBTree

目录

  • 1. 红黑树的概念
  • 2. 红黑树的性质
  • 3. 结点的定义
  • 4. 结点的插入
  • 5. 整体代码

1. 红黑树的概念

红黑树,是一种二叉搜索树,但在每个结点上增加一个存储位表示结点的颜色,可以是Red或Black。 通过对任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树确保没有一条路径会比其他路径长出俩倍,因而是接近平衡的

最短路径:全黑;最长路径:一黑一红交替。

由于avl树要求严格的平衡,因此相比于红黑树来说需要更频繁的旋转来保证平衡,所以整体而言效率是比红黑树要低一点。

在这里插入图片描述

2. 红黑树的性质

  1. 每个结点不是红色就是黑色
  2. 根节点是黑色的
  3. 如果一个节点是红色的,则它的两个孩子结点必须是黑色的,保证没有任何一条路径会出现连续的红节点
  4. 对于每个结点,从该结点到其所有后代叶结点的简单路径上,均包含相同数目的黑色结点
  5. 每个叶子结点都是黑色的(此处的叶子结点指的是空结点)

3. 结点的定义

//枚举颜色
enum Color {RED,BLACK
};template<class K, class V>
struct RBTreeNode {RBTreeNode(const pair<const K, V>& kv):_kv(kv), _left(nullptr), _right(nullptr), _parent(nullptr), _col(RED){ }pair<const K, V> _kv;//需要再增加一个结点颜色信息Color _col;RBTreeNode<const K, V>* _left;RBTreeNode<const K, V>* _right;//同样是需要父亲结点,后续调整旋转需要找到父亲RBTreeNode<const K, V>* _parent;
};

4. 结点的插入

往已经是满足红黑树性质的树中插入一个结点时,待插入结点的颜色一定要设置为红色,为什么?

若插入一个黑色结点,那么必然会违反性质4,若插入红色节点则不一定会违反性质3。

红黑树插入的关键在于要看叔叔结点的颜色,具体情况可分为两种:

  1. 叔叔存在且为红
    在这里插入图片描述
  2. 叔叔不存在或者叔叔存在且为黑
    在这里插入图片描述
    叔叔存在且为黑是第一种情况触发后才会出现:
    在这里插入图片描述

5. 整体代码

红黑树和AVL树都是高效的平衡二叉树,增删改查的时间复杂度都是O( l o g 2 N log_2 N log2N),红黑树不追求绝对平衡,其只需保证最长路径不超过最短路径的2倍,相对而言,降低了插入和旋转的次数,所以在经常进行增删的结构中性能比AVL树更优,而且红黑树实现比较简单,所以实际运用中红黑树更多。

#pragma once
#include <iostream>using namespace std;enum Color {RED,BLACK
};template<class K, class V>
struct RBTreeNode {RBTreeNode(const pair<const K, V>& kv):_kv(kv), _left(nullptr), _right(nullptr), _parent(nullptr), _col(RED){}pair<const K, V> _kv;enum Color _col;RBTreeNode<const K, V>* _left;RBTreeNode<const K, V>* _right;RBTreeNode<const K, V>* _parent;
};template<class K, class V>
class RBTree {typedef RBTreeNode<const K, V> Node;
public:bool insert(const pair<const K, V>& kv) {if (!_root) {_root = new Node(kv);_root->_col = BLACK;return true;}Node* cur = _root;Node* parent = nullptr;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;//parent为红需要一直往上调整while (parent && parent->_col == RED) {Node* grandpa = parent->_parent;if (grandpa->_left == parent) {Node* uncle = grandpa->_right;//叔叔存在且为红if (uncle && uncle->_col == RED) {//把父亲和叔叔染黑//爷爷染红继续往上调整parent->_col = uncle->_col = BLACK;grandpa->_col = RED;cur = grandpa;parent = cur->_parent;}//叔叔不存在或者存在且为黑else {//单纯的一边高(直线)单旋if (cur == parent->_left) {rotateRight(grandpa);parent->_col = BLACK;cur->_col = grandpa->_col = RED;}//折线情况需要双旋else {rotateLeft(parent);rotateRight(grandpa);cur->_col = BLACK;parent->_col = grandpa->_col = RED;}break;}}//同样的逻辑else {Node* uncle = grandpa->_left;if (uncle && uncle->_col == RED) {parent->_col = uncle->_col = BLACK;grandpa->_col = RED;cur = grandpa;parent = cur->_parent;}else {if (parent->_right == cur) {rotateLeft(grandpa);grandpa->_col = cur->_col = RED;parent->_col = BLACK;}else {rotateRight(parent);rotateLeft(grandpa);parent->_col = grandpa->_col = RED;cur->_col = BLACK;}break;}		 }}_root->_col = BLACK;return true;}bool isBlance() {if (_root->_col != BLACK) {return false;}int cnt = 0;Node* cur = _root;while (cur) {cnt += cur->_col == BLACK;cur = cur->_left;}return _isBlance(_root, 0, cnt);}int getHeight() {return getHeight(_root);}private:int getHeight(Node* root) {if (!root) {return 0;}int leftH = getHeight(root->_left);int rightH = getHeight(root->_right);return max(leftH, rightH) + 1;}bool _isBlance(Node* root, int blackcnt, int t) {if (!root) {cout << blackcnt << ' ' << t << endl;return t == blackcnt;}if (root->_col == RED && root->_parent && root->_parent->_col == RED) {return false;}return _isBlance(root->_left, blackcnt + (root->_col == BLACK), t) && _isBlance(root->_right, blackcnt + (root->_col == BLACK), t);}void rotateLeft(Node* parent) {Node* cur = parent->_right;Node* curleft = cur->_left;if (curleft) {curleft->_parent = parent;}parent->_right = curleft;cur->_left = parent;Node* oldparent = parent->_parent;parent->_parent = cur;cur->_parent = oldparent;if (!oldparent) {_root = cur;}else {if (oldparent->_left == parent) {oldparent->_left = cur;}else {oldparent->_right = cur;}}}void rotateRight(Node* parent) {Node* cur = parent->_left;Node* curright = cur->_right;if (curright) {curright->_parent = parent;}parent->_left = curright;cur->_right = parent;Node* oldparent = parent->_parent;parent->_parent = cur;cur->_parent = oldparent;if (!oldparent) {_root = cur;}else {if (oldparent->_left == parent) {oldparent->_left = cur;}else {oldparent->_right = cur;}}}private:Node* _root = nullptr;
};

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

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

相关文章

Cesium 相机设置

1.setView 直接跳转到目的地 // 设置相机位置 const position Cesium.Cartesian3.fromDegrees(113, 31, 20000); // setView通过定义相机目的地&#xff08;方向&#xff09;,直接跳转到目的地 viewer.camera.setView({ destination: position, // 位置设置 orientation: { //…

基于自然语言处理的结构化数据库问答机器人系统

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长 Wechat / QQ 名片 :) 1. 项目简介 知识库&#xff0c;就是人们总结出的一些历史知识的集合&#xff0c;存储、索引以后&#xff0c;可以被方便的检索出来供后人查询/学习。QnA Maker是用于建立知识库的工具&#xff0c;使用…

YOLOv8-Seg改进:分割注意力系列篇 | 高效的通道先验卷积注意力(CPCA) | 中科院 2023.6

🚀🚀🚀本文改进:高效的通道先验卷积注意力(CPCA)方法,支持注意力权重在通道和空间维度上的动态分布; 🚀🚀🚀CPCA 小目标分割检测&复杂场景首选,实现涨点 🚀🚀🚀YOLOv8-seg创新专栏:http://t.csdnimg.cn/KLSdv 学姐带你学习YOLOv8,从入门到创新…

C++初阶--类与对象(3)(图解)

文章目录 再谈构造函数初始化列表隐式类型转换explicit关键字 static成员友元类内部类匿名对象拷贝函数时的一些优化 再谈构造函数 在我们之前的构造函数中&#xff0c;编译器会通过构造函数&#xff0c;对对象中各个成员给出一个适合的初始值&#xff0c;但这并不能称之为初始…

AIX5.3安装weblogic10.3

目录 1安装IBM JDK 1.6 2图形化准备 3安装weblogic 准备 4图形化界面安装 1安装IBM JDK 1.6 1.1检查操作系统 # oslevel 5.3.0.0 # bootinfo -y (显示AIX机器硬件是64位) 64 # bootinfo -K (显示AIX系统内核是64位) 64 因此&#xff0c;系统需要安装64位的jdk&#xff0c;…

基于STC12C5A60S2系列1T 8051单片机串口通信信应用

基于STC12C5A60S2系列1T 8051单片机串口通信应用 STC12C5A60S2系列1T 8051单片机管脚图STC12C5A60S2系列1T 8051单片机串口通信介绍STC12C5A60S2系列1T 8051单片机串口通信的结构基于STC12C5A60S2系列1T 8051单片机串口通信的特殊功能寄存器列表基于STC12C5A60S2系列1T 8051单片…

赛氪助力全国大学生数学竞赛山东赛区圆满举办

近日&#xff0c;全国大学生数学竞赛山东赛区比赛有序进行&#xff0c;赛氪已连续6年助力本项赛事蓬勃发展。在中国高等教育学会高校竞赛评估与管理体系研究专家工作组发布的《2022全国普通高校大学生竞赛分析报告》中&#xff0c;本赛事荣登观察目录。 全国大学生数学竞赛旨在…

【C++破局】C++内存管理之new与deleted剖析

​作者主页 &#x1f4da;lovewold少个r博客主页 ⚠️本文重点&#xff1a;c内存管理部分知识点梳理 &#x1f449;【C-C入门系列专栏】&#xff1a;博客文章专栏传送门 &#x1f604;每日一言&#xff1a;花有重开日&#xff0c;人无再少年&#xff01; 目录 C/C的内存分配机…

管理能力测评,如何提升管理能力?

管理能力是综合能力的体现&#xff0c;通常也解读为组织管理能力&#xff0c;如果要再细分的话&#xff0c;可能还包括有沟通能力&#xff0c;协调能力&#xff0c;组织能力&#xff0c;执行力和专业能力等等。不过没有办法说的太细节&#xff0c;因为每个部分铺开了都是一个独…

基于工业智能网关的汽车充电桩安全监测方案

近年来&#xff0c;我国新能源汽车产业得到快速发展&#xff0c;电动车产量和销量都在持续增长&#xff0c;不仅国内市场竞争激烈&#xff0c;而且也远销海外&#xff0c;成为新的经济增长点。但与此同时&#xff0c;充电设施的运营却面临着安全和效率的双重挑战。 当前的充电桩…

开放式耳机井喷阶段,南卡品牌何以成为“头号玩家”?

对于耳机行业而言,过去两年的聚光灯属于开放式耳机这一才闯入赛道的品类。 在消费电子寒冬持续蔓延的时间节点,夺下属于自己的高光时刻实属不易,毕竟无论是过去数年间高歌猛进的智能可穿戴设备行业,还是更垂直的耳机赛道,现阶段均面临承压的局面。 一面是“前辈”们昔日的“爆…

matlab 读写ENVI标准数据

本博客主要讲解如何读、生成ENVI标准格式的数据。主要分为四部分&#xff1a;读取ENVI头文件、读取ENVI数据、写入ENVI头文件、生成ENVI标准数据&#xff0c;最后附加讲解了本人写的生成hdr文本文件代码。此外&#xff0c;文中还具体介绍写代码的一些思路。 注&#xff1a;完整…

【C++入门】构造函数析构函数

目录 前言 1. 类的默认成员函数 2. 构造函数 2.1 什么是构造函数 2.2 构造函数的特性 3. 析构函数 3.1 什么是析构函数 3.2 析构函数的特性 前言 前边我们已经了解了类和对像的基本概念&#xff0c;今天我们将继续深入了解类。类有6个默认成员函数&#xff0c;即使类中什么都…

一款基于.Net开发、开源、支持多平台云存储文件管理器

目录 01 项目简介02 项目代码03 部分截图04 项目地址 今天给大家推荐一款基于基于.Net开发、开源的&#xff0c;支持多平台的云存储文件管理器。 01 项目简介 Camelotia是一款云存储文件管理器&#xff0c;基于.Net UI框架和ReactiveUI框架开发的&#xff0c;目前支持的平台有…

skynet学习笔记03— 服务

01、API newservice(name, ...)&#xff1a; 阻塞的形势启动一个名为 name 的新服务&#xff0c;待start函数执行完后会返回这个服务的地址。uniqueservice(name, ...)&#xff1a;针对于当前节点&#xff0c;启动一个唯一服务&#xff08;相当于单例&#xff09;&#xff0c;…

STM32F103C8T6第三天:pwm、sg90、超声波、距离感应按键开盖震动开盖蜂鸣器

1. 定时器介绍1&#xff08;317.21&#xff09; 软件定时&#xff08;之前的定时方法&#xff09;&#xff08;软件延时&#xff09;缺点&#xff1a;不精确、占用CPU资源 void Delay500ms() //11.0592MHz {unsigned char i, j, k;_nop_();i 4;j 129;k 119;do{do{while (-…

Flink SQL -- 概述

1、Flink SQL中的动态表和连续查询 1、动态表&#xff1a; 因为Flink是可以做实时的&#xff0c;数据是在不断的变化的&#xff0c;所以动态表指的是Flink中一张实时变换的表&#xff0c;表中会不断的有新的数据。但是这张表并不是真正的物理表。 2、连续查询&#xff1a; 连续…

网络安全深入学习第八课——代理与端口转发

文章目录 一、什么是代理二、正向代理三、反向代理四、正向和反向代理模拟复现 一、什么是代理 代理服务器英文全称是Proxy Server&#xff0c;其功能就是代理网络用户去取得网络信息。 形象的说&#xff1a;它是网络信息的中转站。在一般情况下&#xff0c;我们使用网络浏览…

自动驾驶学习笔记(八)——路线规划

#Apollo开发者# 学习课程的传送门如下&#xff0c;当您也准备学习自动驾驶时&#xff0c;可以和我一同前往&#xff1a; 《自动驾驶新人之旅》免费课程—> 传送门 《Apollo Beta宣讲和线下沙龙》免费报名—>传送门 文章目录 前言 路线规划 路由元素 路径搜索 最优…

P1529 [USACO2.4] 回家 Bessie Come Home 题解

文章目录 题目描述输入格式输出格式样例样例输入样例输出 提示完整代码 题目描述 现在是晚餐时间&#xff0c;而母牛们在外面分散的牧场中。 Farmer John 按响了电铃&#xff0c;所以她们开始向谷仓走去。 你的工作是要指出哪只母牛会最先到达谷仓&#xff08;在给出的测试数…