hello树先生——红黑树

2024-09-02 22:04
文章标签 红黑树 hello 先生

本文主要是介绍hello树先生——红黑树,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

红黑树

  • 一.什么是红黑树
  • 二.红黑树的实现
    • 1.创建树节点结构
    • 2.插入功能的实现
  • 三.提供一些常见二叉树接口
  • 四.进行平衡测试

一.什么是红黑树

在这里插入图片描述

红黑树是一种自平衡的二叉搜索树,具有以下特性:

  • 节点颜色:每个节点要么是红色,要么是黑色。
  • 根节点:根节点始终是黑色。
  • 红色节点:红色节点的子节点不能是红色(即没有两个连续的红色节点)。
  • 黑色节点:从任何节点到其每个叶子节点的路径上,必须包含相同数量的黑色节点。
  • 叶子节点:所有叶子节点(空节点)都是黑色。
    红黑树的这些特性确保了树的高度是对数级别,从而保证了基本操作(如插入、删除和查找)的时间复杂度为O(log n)。这种结构常用于实现关联数组和集合等数据结构。

相较于AVL树,他的高度可能会更高,但由于没有那么多严格旋转操作,所以插入效率会略高

二.红黑树的实现

1.创建树节点结构

由于我们通过树节点的颜色来区分,是否平衡,所以提前定义一下红黑颜色,这里我们使用枚举法定义颜色。

enum color
{RED,BLACK
};

节点结构类似于AVL树,三个指针链接和pair类型数据,唯一加了一个颜色特征,插入节点默认红色。

template<class K,class V>
struct RBTreeNode
{pair<K, V>  _kv;RBTreeNode<K, V>* _left;RBTreeNode<K, V>* _right;RBTreeNode<K, V>* _parent;color _col;RBTreeNode(const pair<K, V>& kv):_left(nullptr),_right(nullptr),_parent(nullptr),_col(RED),_kv(kv){}};

2.插入功能的实现

bool Insert(const pair<K, V>& kv)

插入分为两种大情况,父亲为黑色或红色,如果黑色那么我们插入新节点就不存在破坏规则,如果是红色,则需要进行调整。

  • 如果当前树无节点则,插入根节点
if (_root == nullptr){node* cur = new node(kv);_root = cur;_root->_col = BLACK;return true;}
  • 寻找插入位置,并记录父节点位置
//寻找节点node* parent = nullptr;node* cur = _root;while (cur){if (kv.first < cur->_kv.first){parent = cur;cur = cur->_left;}else if (kv.first > cur->_kv.first){parent = cur;cur = cur->_right;}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->_col == RED)
{//调整逻辑
}

若插入节点的叔叔节点存在且为红色,那么仅需变色操作,找到parent的parent将其反色,将parent与uncle反色,之后将cur交给祖父,重复操作判断
在这里插入图片描述

如图为,父亲是左子树的情况,右子树类似
代码先判断父亲是左还是右子树,从而找到叔叔节点

				node* grandparent = parent->_parent;if (grandparent->_left == parent){node* uncle = grandparent->_right;//叔叔存在且为红if (uncle && uncle->_col == RED){parent->_col = uncle->_col = BLACK;grandparent->_col = RED;//继续更新判断cur = grandparent;parent = cur->_parent;}//叔叔不存在或者为黑else{//下方继续讲解}   }

若叔叔不存在或存在且为黑,则分为两种子情况,类似与AVL树的左左高和左右高形状
1.左左高,即插入节点在左侧
在这里插入图片描述
首先将其进行祖父为旋转点旋转,之后将父亲和祖父颜色反转

			if (parent->_left == cur){//左插//		   g//		p      u// curRotateR(grandparent);grandparent->_col = RED;parent->_col = BLACK;}

2.左右高,将其旋转两次,parent左旋,grandparent右旋
在这里插入图片描述
然后将祖父和cur进行变色
在这里插入图片描述

//右插//		   g//		p      u//        curRotateL(parent);RotateR(grandparent);grandparent->_col = RED;cur->_col = BLACK;

叔叔是黑色或不存在的情况,进行调整后直接跳出break就好

父亲是右子树完全类似,下面不在讲解,提供代码供参考

				else{node* uncle = grandparent->_left;//叔叔存在且为红if (uncle && uncle->_col == RED){parent->_col = uncle->_col = BLACK;grandparent->_col = RED;//继续更新判断cur = grandparent;parent = cur->_parent;}//叔叔不存在或者为黑else{if (parent->_right == cur){//右插//		   g//		u      p//                curRotateL(grandparent);grandparent->_col = RED;parent->_col = BLACK;}else{//右插//		   g//		u      p//        curRotateR(parent);RotateL(grandparent);grandparent->_col = RED;cur->_col = BLACK;}break;}}

最后将根节点统一变为黑色,并返回true

			_root->_col = BLACK;return true;

如何旋转在AVL树中详细讲解过

三.提供一些常见二叉树接口

求高度,数量,和中序遍历

	   int height(){return _height(_root);}int size(){return _size(_root);}void InOrder(){_InOrder(_root);cout << endl;}
		void _InOrder(node* root){if (root == nullptr)return;_InOrder(root->_left);cout << root->_kv.first << " " << root->_kv.second << endl;_InOrder(root->_right);}int _height(node* root){if (root == nullptr){return 0;}return max(_height(root->_left), _height(root->_right)) + 1;}int _size(node* root){if (root == nullptr){return 0;}return root == nullptr ? 0 : _size(root->_left) + _size(root->_right) + 1;}

四.进行平衡测试

主要测试这颗红黑树是否符合

  • 根节点为黑色
  • 每条路径黑色节点数量相同
  • 不能连续两个红色节点出现
    这里我们采取从根节点向下递归,加入两个参数,记录任意一条路径下的黑色节点数量,和一个count统计当前路径下黑色节点的数目
		bool IsBalance(){if (_root->_col == RED){return false;}int refNum = 0;node* cur = _root;while (cur){if (cur->_col == BLACK){++refNum;}cur = cur->_left;}return Check(_root, 0, refNum);}bool Check(node* root, int blackNum, const int refNum){if (root == nullptr){//cout << blackNum << endl;if (refNum != blackNum){cout << "存在黑色节点的数量不相等的路径" << endl;return false;}return true;}if (root->_col == RED && root->_parent->_col == RED){cout << root->_kv.first << "存在连续的红色节点" << endl;return false;}if (root->_col == BLACK){blackNum++;}return Check(root->_left, blackNum, refNum)&& Check(root->_right, blackNum, refNum);}

然后我们随机产生一些随机数测试一番,顺便记录各功能效率

void test2()
{RBTree<int, int> a;srand((unsigned int)time(0));int N = 1000000;size_t ret1 = clock();for (int i = 0; i < N; i++){int num = rand() + i;a.Insert({ num,num });}size_t ret2 = clock();cout << "insert->time : " << ret2 - ret1 << endl;size_t ret3 = clock();for (int i = 0; i < N; i++){int num = rand() + i;a.find(num);}size_t ret4 = clock();cout << "insert->time : " << ret2 - ret1 << endl;cout << "find->time : " << ret4 - ret3 << endl;cout << "size-> " << a.size() << endl;cout << "height-> " << a.height() << endl;cout << a.IsBalance() << endl;
}

在这里插入图片描述

这篇关于hello树先生——红黑树的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1131194

相关文章

【Spring boot】编写代码及测试用例入门之 Hello Spring boot _踩坑记

先贴下目录: 这是我从 start.spring.io 里下载的依赖Web的模板 // DemoApplication.javapackage com.abloume.springboot.blog.demo;import org.springframework.boot.SpringApplication;import org.springframework.boot.autocon

【JFinal】IDEA+maven上手JFinal之Hello World!

一、New Project 1、在 IDEA 环境下新建 Project 项目 2、选择创建 Maven 项目,并且不使用模板 3、输入 Maven 的 GroupId 和 ArtifactId 4、输入项目名称 二、将当前 Project 改为 POM 工程 将项目的 jfinal-web-demo 作为项目的 parent 工程,用于定义 maven 依赖包的版本信息、

红黑树的旋转

红黑树的基本性质 红黑树与普通的二叉搜索树不同,它在每个节点上附加了一个额外的属性——颜色,该颜色可以是红色或黑色。通过引入这些颜色,红黑树能够维持以下 5 个基本性质,以确保树的平衡性: 每个节点是红色或黑色。根节点是黑色。所有叶子节点(NIL 节点)是黑色。如果一个节点是红色的,那么它的两个子节点都是黑色的(即,红色节点不能有红色子节点)。从任一节点到其每个叶子节点的所有路径上都包含相同数

接下来的这个故事就来自于我的先生,一个交警的口述

这可是没有过的事情。先生是个交通警察,在事故科工作已经五、六年了,对于生离死别、阴阳两隔,用他自己的话说是已经有些麻木了;不用说他,就连我,对那些卷宗里血淋淋的照片都已经有些漠然。他的办公室常有悲悲切切的人来哭诉,他却总能在复议时做到不掺杂感情。我是个爱哭的女人,偏偏先生对于眼泪早已有了职业的免疫力,他说要是每个事故他都要为每个逝者陪眼泪的话,他早就活不下去了,但是今天不同,他分明是掉过泪了。

hello,大家好。

由于最近工作变动,目前是从河北来到了广东。 顾不上写博客了,请大家谅解。 后续会慢慢的恢复正常的节奏,很感谢大家的关注。

C++笔记19•数据结构:红黑树(RBTree)•

红黑树 1.简介:         红黑树,是一种二叉搜索树,但在每个结点上增加一个存储位表示结点的颜色,可以是Red或 Black。 通过对任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树确保没有一条路 径会比其他路径长出俩倍,因而是接近平衡的。 当搜索二叉树退化为单支树时,搜索效率极低,为了使搜索效率高,建立平衡搜索二叉树就需要"平衡树"来解决。上一篇博客介绍了AVL树,这

java-在idea中antrl的hello world

java-在idea中antrl的hello world 1. 在idea中安装ANTLR V4的插件2. 下载ANTLR的jar包3. idea中创建普通的java项目4. 创建一个Hello.g4的文件5. 使用idea生产接口文件6. java创建一个类和main方法7. 调试输出8. 参考链接 1. 在idea中安装ANTLR V4的插件 路径如下,安装完成后重启ide

java-antrl手敲命令的hello world

java-antrl手敲命令的hello world 环境步骤1. 下载ANTLR的jar包2. 新建一个g4文件3. 生成语法对应的java文件4. 编译语法对应的java文件5. 测试语法5.1 打印测试信息5.2 查看语法分析树 6. 注意事项6.1 每一个antlr4版本的jar包都对应java的相应版本,要对应。6.2 [@1,6:10='parrt',<ID>,1:6]解析6.3

汇编语言输出“Hello World!“

1.软件 Nasmide64.exe(李忠老师编写) Fixvhdw64.exe(李忠老师编写) VirtualBox虚拟机(免费 开源) 2.过程 01.Fixvhdw64.exe输入以下代码: mov ax,0xb800mov ds,axmov byte [0x00],'H'mov byte [0x02],'e'mov byte [0x04],'l'mov byte [0

数据结构(13)——平衡二叉树(红黑树)

欢迎来到博主的专栏——数据结构 博主ID:代码小号 文章目录 红黑树红黑树节点之间的关系红黑树的插入uncle节点为红色uncle节点是黑色或者没有uncle节点 红黑树 平衡二叉树最出名的除了AVL树之外就是红黑树(RBTree),所谓红黑树,即拥有以下特性的平衡二叉树 (1)每个节点要么是红色,要么是黑色 (2)根节点必须是黑色 (3)红色节点的子节点必须是黑色 (