红黑树-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.mzph.cn/news/139905.shtml

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

相关文章

长安链可验证数据库,保证数据完整性的可信存证方案

近日&#xff0c;长安链发布“可验证数据库”实现了链上链下协同存储及数据完整性保证&#xff0c;显著提升长安链存储能力的可扩展性。 可信存证是联盟链最典型的应用场景&#xff0c;被广泛应用在司法、工业、农业、贸易等领域。联盟链的存证应用主要分为两个阶段&#xff1…

通过easyexcel导出数据到excel表格

这篇文章简单介绍一下怎么通过easyexcel做数据的导出&#xff0c;使用之前easyui构建的歌曲列表crud应用&#xff0c;添加一个导出按钮&#xff0c;点击的时候直接连接后端接口地址&#xff0c;在后端的接口完成数据的导出功能。 前端页面完整代码 let editingId; let request…

【Python】一篇带你掌握数据容器之列表

目录 前言&#xff1a; 一、列表 1.列表的定义 2.列表的下标索引 3.列表的常用操作 &#xff08;1&#xff09;index方法&#xff1a;查找某元素的下标 (2)修改特定位置下标的元素 &#xff08;3&#xff09;insert&#xff08;下标&#xff0c;元素&#xff09;方法&a…

基于SpringBoot+Vue的在线学习平台系统

基于SpringBootVue的在线学习平台系统的设计与实现~ 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringBootMyBatisVue工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 主页 用户界面 登录界面 管理员界面 摘要 本文设计并实现了一套基于Spri…

Nuxt.js——基于 Vue 的服务端渲染应用框架

文章目录 前言一、知识普及什么是服务端渲染什么是客户端渲染&#xff1f;服务端渲染与客户端渲染那个更优秀&#xff1f; 二、Nuxt.js的特点Nuxt.js的适用情况&#xff1f; 三、Vue是如何实现服务端渲染的&#xff1f;安装依赖使用vue安装 Nuxt使用npm install安装依赖包使用n…

基于springboot实现桥牌计分管理系统项目【项目源码】

基于springboot实现桥牌计分管理系统演示 JAVA简介 JavaScript是一种网络脚本语言&#xff0c;广泛运用于web应用开发&#xff0c;可以用来添加网页的格式动态效果&#xff0c;该语言不用进行预编译就直接运行&#xff0c;可以直接嵌入HTML语言中&#xff0c;写成js语言&#…

基于飞蛾扑火算法优化概率神经网络PNN的分类预测 - 附代码

基于飞蛾扑火算法优化概率神经网络PNN的分类预测 - 附代码 文章目录 基于飞蛾扑火算法优化概率神经网络PNN的分类预测 - 附代码1.PNN网络概述2.变压器故障诊街系统相关背景2.1 模型建立 3.基于飞蛾扑火优化的PNN网络5.测试结果6.参考文献7.Matlab代码 摘要&#xff1a;针对PNN神…

第一百七十一回 SearchBar组件

文章目录 1. 概念介绍2. 使用方法3. 代码与效果3.1 示例代码3.2 运行效果 4. 内容总结 我们在上一章回中介绍了"Material3中的IconButton"相关的内容&#xff0c;本章回中将 介绍SearchBar组件.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 概念介绍 我们在…

2023 ChinaJoy后,Flat Ads成为游戏、社交出海的新选择

今年ChinaJoy 展会&#xff0c;共吸引了来自世界各地的 500 多家企业参展&#xff0c;预计吸引超过33万人次参观。ChinaJoy年年有&#xff0c;那今年对于行业来说有什么新变化呢&#xff1f; 01 出海热潮不减&#xff0c;新增客户明显提升 据不完全统计&#xff0c;展会期间前…

《红蓝攻防对抗实战》十二.内网穿透之利用ICMP协议进行隧道穿透

内网穿透之利用ICMP协议进行隧道穿透 一.前言二.前文推荐三.利用ICMP协议进行隧道穿透1.ICMPsh获取反弹shell2.PingTunnel 搭建隧道 四.本篇总结 一.前言 本文介绍了利用ICMP协议进行隧道穿透的方法。ICMP协议不需要开放端口&#xff0c;可以将TCP/UDP数据封装到ICMP的Ping数据…

Error creating bean with name ‘apiModelSpecificationReader‘ defined in URL

问题&#xff1a; 启动项目的时候&#xff0c;报错了 org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name apiModelSpecificationReader defined in URL [jar:file:/D:/.gradle/caches/modules-2/files-2.1/io.springfox/sp…

基于springboot实现驾校管理系统项目【项目源码】

基于springboot实现驾校管理系统演示 JAVA简介 JavaScript是一种网络脚本语言&#xff0c;广泛运用于web应用开发&#xff0c;可以用来添加网页的格式动态效果&#xff0c;该语言不用进行预编译就直接运行&#xff0c;可以直接嵌入HTML语言中&#xff0c;写成js语言&#xff0…

免费分享一套基于Springboot+Vue的在线考试系统,挺漂亮的

大家好&#xff0c;我是java1234_小锋老师&#xff0c;看到一个不错的SpringbootVue的在线考试系统&#xff0c;分享下哈。 项目视频演示 【免费】springbootvue在线考试系统 Java毕业设计_哔哩哔哩_bilibili【免费】springbootvue在线考试系统 Java毕业设计项目来自互联网&a…

劲松HPV防治诊疗中心发布:HPV感染全面防治解决方案

在当今社会&#xff0c;HPV(人乳头瘤病毒)感染问题已成为广大公众关注的焦点。作为一种高度传染性的病毒&#xff0c;HPV感染不仅可能导致生殖器疣&#xff0c;还可能引发各种癌症。面对这一严重威胁&#xff0c;劲松HPV防治诊疗中心以其专业的医疗团队、正规的治疗流程和全方位…

ZYNQ_project:key_led

条件里是十进制可以不加进制说明&#xff0c;编译器默认是10进制&#xff0c;其他进制要说明。 实验目标&#xff1a; 模块框图&#xff1a; 时序图&#xff1a; 代码&#xff1a; include "para.v"module key_filter (input wire …

长春理工大学漏洞报送证书

获取来源&#xff1a;edusrc&#xff08;教育漏洞报告平台&#xff09; url&#xff1a;主页 | 教育漏洞报告平台 兑换价格&#xff1a;10金币 获取条件&#xff1a;提交长春理工大学任意中危或以上级别漏洞

Linux驱动开发——PCI设备驱动

目录 一、 PCI协议简介 二、PCI和PCI-e 三、Linux PCI驱动 四、 PCI设备驱动实例 五、 总线类设备驱动开发习题 一、 PCI协议简介 PCI (Peripheral Component Interconnect&#xff0c;外设部件互联) 局部总线是由Intel 公司联合其他几家公司一起开发的一种总线标准&#…

【数据结构】树与二叉树(十二):二叉树的递归创建(算法CBT)

文章目录 5.2.1 二叉树二叉树性质引理5.1&#xff1a;二叉树中层数为i的结点至多有 2 i 2^i 2i个&#xff0c;其中 i ≥ 0 i \geq 0 i≥0。引理5.2&#xff1a;高度为k的二叉树中至多有 2 k 1 − 1 2^{k1}-1 2k1−1个结点&#xff0c;其中 k ≥ 0 k \geq 0 k≥0。引理5.3&…

mysql基础 --子查询

文章目录 子查询子查询案例 子查询 一个查询语句&#xff0c;嵌套在另一个查询语句内部&#xff1b;子查询先执行&#xff0c;其结果被外层主查询使用&#xff1b;子查询放入括号内&#xff1b;子查询放在比较条件的右侧&#xff1b;子查询返回一条&#xff0c;为单行子查询(对…

python工具HIKVISION视频编码设备接入网关任意文件下载

python工具 构造payload /serverLog/downFile.php?fileName../web/html/serverLog/downFile.php漏洞证明 文笔生疏&#xff0c;措辞浅薄&#xff0c;望各位大佬不吝赐教&#xff0c;万分感谢。 免责声明&#xff1a;由于传播或利用此文所提供的信息、技术或方法而造成的任何…