数据结构: 红黑树

目录

1.红黑树概念

2.红黑树性质

3.调整

1.如果p和u都是红色,将其都改为黑色即可,然后向上调整

2.如果p红(u黑/u不在),这时候左子树两红,于是给右子树一个红(旋转+变色)

2.1右单旋 + 变色- p变黑, g变红, 达到给右子树一个红节点的效果, 并保持每条路径上黑色节点的个数相同

2.2左右双旋转 + 变色

2.3左单旋 + 变色

2.4右左双选 + 变色

4.红黑树的简单实现

4.1红黑树的定义

4.2相关功能

插入

检查

获取最左/右侧的节点

检查树种是否存在data节点

4.3默认成员函数

测试用例:

1.插入

2.检查

3.获取最左/右侧节点

4.在树种查找节点


1.红黑树概念

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

2.红黑树性质

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

最短路径: 全黑

最长路径: 一黑一红交替

红黑树就能保证:其最长路径中节点个数不会超过最短路径节点个数的两倍

红黑树优势: 旋转次数更少

新插入的节点默认是红色

--1.如果是黑色, 一定违反了规则4 会影响所有路径

--2.如果是红色, 当插入到红色节点后面,违反规则3 , 当插入到黑色节点的后面,不违反规则

3.调整

什么时候需要修改红黑树?--当插入到红色节点后面的时候

1.如果p和u都是红色,将其都改为黑色即可,然后向上调整

  • -然后将g改为红(g原来为黑,我们已经把p,u改为黑了,会多一个黑节点,违反规则4,需要把g改为红)
  • -当然改为红后,g的p可能也是红,继续往上调整即可(把cur = g),如果最后调到根,要将根变黑

2.如果p红(u黑/u不在),这时候左子树两红,于是给右子树一个红(旋转+变色)

-这种情况讨论cur的插入位置 ,来决定其需要怎么旋转(单旋,双旋)

--p是g的左 ,且插入的节点在左子树

2.1右单旋 + 变色
- p变黑, g变红, 达到给右子树一个红节点的效果, 并保持每条路径上黑色节点的个数相同

2.2左右双旋转 + 变色

--p是g的右, 且插入的节点在右子树

2.3左单旋 + 变色

2.4右左双选 + 变色

4.红黑树的简单实现

4.1红黑树的定义

节点

RBTree

4.2相关功能

插入

1.找到节点的位置

2.链接节点

3.判断此时p是不是红色, 且存在 (默认插入的节点是红色), 是的话就需要调整

  --p,u存在且都为红 ===> 直接将p,u变为黑色,g变红色, 然后向上调整,

  如果调到根(要将其变黑)

  --p红, u红/u不在    ===> 对插入节点位置进行讨论

1.p是g的左, cur是 p的左  ===> g右单旋

2.p是g的左, cur是p的右   ===>  p左旋, g右旋

3.p是g的右, cur是p的右   ===>  g左单旋

4.p是g的右, cur是p的左   ===>  p右旋,g左旋

代码:

1.找到节点的位置 2.链接节点

​​​​​​​​​​​​​​

3.判断此时p是不是红色, 且存在 (默认插入的节点是红色), 是的话就需要调整

效果:

检查

  1. 判断根节点是黑色的(规则2)
  2. 判断有无连续的红色节点(规则3)
  3. 判断每条路径上的黑色节点个数是否相等(规则4)                                                             --这里随便选取一条路径的黑色节点数作为基准值, 用来和对比其它路径黑节点的个数

代码:

	//红黑树的检查bool Is_RBTree() {return _Is_RBTree(_root);}//红黑树的检查bool _Is_RBTree(Node* root){//规则2:根节点是黑色的if (root == nullptr) return true;	if (root->_color != BLACK) return false;//规则3:不能有连续的红色节点//规则4:每条路径上的黑色节点个数相等Node* cur = root; int base_nums = 0;while (cur) {if (cur->_color == BLACK) base_nums++;cur = cur->_left;}Check(root,base_nums,0);}bool Check(Node* root,int base_nums,int block_nums) {if (root == nullptr) {if (base_nums != block_nums) return false;return true;}//检查有没有连续的红色节点if (root->_parent && root->_color == RED && root->_parent->_color == RED)return false;//遇到一个黑色节点就++if (root->_color == BLACK) block_nums++;return Check(root->_left,base_nums,block_nums) && Check(root->_right,base_nums,block_nums);}

获取最左/右侧的节点

	//获取红黑树最左侧节点Node* LeftMost(){Node* cur = _root;//空树if (cur == nullptr) return nullptr;while (cur->_left){cur = cur->_left;}return cur;}//获取红黑树最右侧节点Node* RightMost(){Node* cur = _root;//空树if (cur == nullptr) return nullptr;while (cur->_right){cur = cur->_right;}return cur;}

检查树种是否存在data节点

	//检测红黑树中是否存在值为data的节点Node* Find(const T& data){Node* cur = _root;while (cur){if (cur->_data > data)cur = cur->_left;else if (cur->_data < data)cur = cur->_right;else return cur;}return nullptr;}

4.3默认成员函数

--构造函数

这里传了缺省值(可不写)

--拷贝构造

思路:使用前序遍历, 构造红黑树

--赋值运算符

思路: 交换_root

--析构函数

后序遍历,删除节点

测试用例:

1.插入

2.检查

正常情况:

异常:

屏蔽掉颜色的调整

修改默认生成黑色节点

3.获取最左/右侧节点

4.在树种查找节点

代码:RB-Tree/RB-Tree · 朱垚/数据结构练习 - 码云 - 开源中国 (gitee.com)

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

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

相关文章

栈和队列的C++模拟实现

一、栈stack 1.介绍&#xff08;库里面的文档介绍&#xff09; 1. stack是一种容器适配器&#xff0c;专门用在具有后进先出操作的上下文环境中&#xff0c;其删除只能从容器的一端进行元素的插入与提取操作。 2. stack是作为容器适配器被实现的&#xff0c;容器适配器即是对…

有效管理token,充分发挥ChatGPT的能力

目录 给提供了 Token 的计算工具,来理解一下Token的计算方式,网址如下: 窗口如下: 实际消耗 Token 数量为 59个,换算之后为2.1-2.2的比例,即一个汉字消耗2.12.2个Token, 再测一下英文的Token消耗,包含空格在内,一共52个英文字母,消耗Token 13个,正好对应13个单词,…

vue3入门级笔记

一.vue3的优势 二.使用create-create-vue搭建vue3项目 三.项目目录和关键文件 四.组合式API 1&#xff0c;setup的写法和执行时机 执行时机比beforeCreate还要早 setup函数中&#xff0c;获取不到this(this 是undefined) 数据 和 函数 &#xff0c;需要在 setup 最后 return&a…

策略模式在社会中的应用

文章目录 &#x1f31f; 如何将设计模式策略模式运用到社会当中&#x1f34a; 什么是策略模式&#x1f34a; 策略模式在社会中的应用&#x1f389; 1. 政治选举&#x1f389; 2. 商业竞争&#x1f389; 3. 教育培训 &#x1f34a; 策略模式的优缺点&#x1f389; 优点&#x1f…

类加载的过程总结以及双亲委派模型[JVM]

类加载过程 类一共有七个生命周期:加载->验证->准备->解析->初始化->使用->卸载 加载&#xff08;加载字节码文件&#xff0c;生成.class对象&#xff09; 加载是类加载的第一个阶段。 加载阶段的任务是在类文件从磁盘加载到内存中&#xff0c;通常是从cl…

【LCR 170. 交易逆序对的总数】

目录 一、题目描述二、算法原理三、代码实现3.1升序&#xff1a;3.2降序&#xff1a; 一、题目描述 二、算法原理 三、代码实现 3.1升序&#xff1a; class Solution { public:int mergeSort(vector<int>& nums, int left, int right){if (left > right){retur…

mysql varchar int

年龄是数字类型int SELECT * FROM test ORDER BY age; 年龄是字符类型varchar SELECT * FROM test ORDER BY code; 第1种 补前导0可以和数字一样排序 MySQL会比较字符的ASCII值&#xff0c;并根据这些值来确定字符的排列顺序。 印象中oracle好像也是吧。 ASCII (American …

webgl计算包围盒大小

使用three.js&#xff1b; 代码&#xff1b; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><title>第一个three.js 示例</title><style>body {margin: 0;overflow: hidden;}</style><…

选择什么电容笔比较好?平板手写笔推荐

由于苹果Pencil的热销&#xff0c;让华国内市场上&#xff0c;也出现了不少的平替式电容笔&#xff0c;这些产品&#xff0c;有好有坏&#xff0c;价格也很公道。不过&#xff0c;也有很多产品的价格都很平价。我是一个拥有多年经验的数码发烧友&#xff0c;在前几年就开始用上…

【Django 04】Serialization 序列化的高级使用

序列化器 serializers 序列化器的作用 序列化将 queryset 和 instance 转换为 json/xml/yaml 返回给前端 反序列化与序列化则相反 定义序列化器 定义类&#xff0c;继承自 Serializer 通常新建一个 serializers.py 文件 撰写序列化内容 suah as 目前只支持 read_only 只…

IDEA 新版本设置菜单展开

使用了新版本的IDEA 新UI后&#xff0c;常用的file&#xff0c;view&#xff0c;菜单看不见了&#xff0c;不太适应&#xff0c;找了一下&#xff0c;有个配置可以修改。 打开settings里面把show main menu in a separate toolbar勾选上&#xff0c;应用保存就可以了

线性代数1:线性方程和系统

图片来自施泰德博物馆 Digital Collection (staedelmuseum.de) 一、前言 通过这些文章&#xff0c;我希望巩固我对这些基本概念的理解&#xff0c;同时如果可能的话&#xff0c;通过我希望成为一种基于直觉的数学学习方法为其他人提供额外的清晰度。如果有任何错误或机会需要我…

Java并发编程常见面试题总结

梳理Java并发编程相关的面试题&#xff0c;主要参考《JAVA并发编程实战》(Brian Goetz, Joshua Bloch, David Holmes, Tim Peierls, Joseph Bowbeer, Doug Lea 著, 韩锴, 方妙 译)一书&#xff0c;其余部分整合网络相关内容。注意&#xff0c;关于Java基础相关的面试题可以参考…

数据结构-树的概念结构及存储

&#x1f5e1;CSDN主页&#xff1a;d1ff1cult.&#x1f5e1; &#x1f5e1;代码云仓库&#xff1a;d1ff1cult.&#x1f5e1; &#x1f5e1;文章栏目&#xff1a;数据结构专栏&#x1f5e1; 目录 一、树的基本概念及结构 1树的概念 2树的存储 二、二叉树的概念及结构 1二叉树的概…

什么是t检验?

t检验&#xff08;t-test&#xff09;是一种统计方法&#xff0c;用于比较两组数据之间的平均值是否存在显著差异。它通常用于分析两组样本的平均值是否具有统计学上的显著性差异。t检验基于正态分布的假设&#xff0c;它计算两组数据之间的t值&#xff0c;然后通过与t分布表进…

Android笔记(七)Android JetPack Compose组件搭建Scaffold脚手架

在去年2022年曾发布一篇关于脚手架的文章&#xff1a;“Android JetPack Compose组件中Scaffold的应用” 。但是Android的版本从12变更到13及以上版本&#xff0c;导致一些细节的实现存在不同。在本文中&#xff0c;将从头开始介绍整个脚手架的搭建过程。 一、新建项目模块 在…

安装Docker

本安装教程参考Docker官方文档&#xff0c;地址如下&#xff1a;https://docs.docker.com/engine/install/centos/ 卸载旧版 首先如果系统中已经存在旧的Docker&#xff0c;则先卸载&#xff1a; yum remove docker \ docker-client \ docker-client-latest \ docker-common…

经典题型---旋转数组

经典题型—旋转数组 文章目录 经典题型---旋转数组一、题目二、代码实现 一、题目 给定一个整数数组 nums&#xff0c;将数组中的元素向右轮转 k 个位置&#xff0c;其中 k 是非负数。 示例 1: 输入: nums [1,2,3,4,5,6,7], k 3 输出: [5,6,7,1,2,3,4] 解释: 向右轮转 1 步…

Ubuntu系统下使用docker容器配置nginx并部署前端项目

1.下载 Nginx 镜像 命令 描述 docker pull nginx 下载最新版 Nginx 镜像 :2. 创建要挂载的宿主机目录 启动前需要先创建 Nginx 外部挂载的配置文件&#xff08; /home/nginx/conf/nginx.conf&#xff09; 之所以要先创建 , 是因为 Nginx 本身容器只存在 / etc/nginx 目录 ,…

识别准确率竟如此高,实时语音识别服务

前言 本文将介绍一个准确率非常高的语音识别框架&#xff0c;那就是FunASR&#xff0c;这个框架的模型训练数据超过几万个小时&#xff0c;经过测试&#xff0c;准确率非常高。本文将介绍如何启动WebSocket服务和Android调用这个服务来实时识别&#xff0c;一边说话一边出结果…