红黑树(思维导图详解版)

news2024/11/24 16:21:55

目录

资源已上传

实现代码

测试代码


资源已上传

部分图片

实现代码

注意判断是否为红黑树的代码实现,实现代码中红黑树的删除

#pragma once
#include<iostream>
using namespace std;

enum Color_Type
{
	Red,
	Black
};


template<class K,class V>
struct RBTreeNode
{
	pair<K, V> _kv;

	RBTreeNode* _parent;
	RBTreeNode* _left;
	RBTreeNode* _right;
	Color_Type _color;

	RBTreeNode(const pair<K, V> kv)
		: _kv(kv)
		, _parent(nullptr)
		, _left(nullptr)
		, _right(nullptr)
		, _color(Red)
	{}
		
};

template<class K, class V>
class RBTree
{
	typedef RBTreeNode<K, V> Node;
private:
	Node* _root;
public:
	RBTree()
		:_root(nullptr)
	{}

	bool Insert(const pair<K, V>& kv)
	{
		if (_root == nullptr)
		{
			_root = new Node(kv);
			_root->_color = 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);
		cur->_color = Red;
		
		if (cur->_kv.first < parent->_kv.first) {
			parent->_left = cur;
			cur->_parent = parent;
		}
		else
		{
			parent->_right = cur;
			cur->_parent = parent;
		}

		//父节点为红色,插入后还需做调整
		while (parent && parent->_color == Red)
		{
			Node* grandfather = parent->_parent;
			if (parent == grandfather->_left)
			{
				Node* uncle = grandfather->_right;
				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)
					{
						//	  g
						//	p
						//c
						rotateR(grandfather);
						parent->_color = Black;
						grandfather->_color = Red;
					}
					else
					{
						//	g
						//p	
						//	c
						rotateL(parent);
						rotateR(grandfather);
						cur->_color = Black;
						grandfather->_color = Red;
					}
					break;
				}
			}
			else
			{
				Node* uncle = grandfather->_left;
				// u存在且为红
				if (uncle && uncle->_color == Red)
				{
					// 变色
					parent->_color = uncle->_color = Black;
					grandfather->_color = Red;

					// 继续向上处理
					cur = grandfather;
					parent = cur->_parent;
				}
				else
				{
					if (cur == parent->_right)
					{
						// g
						//	  p
						//       c
						rotateL(grandfather);
						grandfather->_color = Red;
						parent->_color = Black;
					}
					else
					{
						// g
						//	  p
						// c
						rotateR(parent);
						rotateL(grandfather);
						cur->_color = Black;
						grandfather->_color = Red;
					}
					break;
				}
			}
		}

		_root->_color = Black;
		return true;
	}
	
	bool IsBalance()
	{
		return _IsBalance(_root);
	}

	int Height()
	{
		return _Height(_root);
	}

	bool checkColor(Node* root, int blacknum, int basenum)
	{
		if (root == nullptr)
		{
			if (blacknum != basenum)
			{
				return false;
			}
			return true;
		}

		if (root->_color == Black)
		{
			++blacknum;
		}

		if (root->_parent && root->_parent->_color == Red && root->_color == Red)
		{
			cout << root->_kv.first << "出现连续红色节点" << endl;
			return false;
		}

		return  checkColor(root->_left, blacknum, basenum) && checkColor(root->_right, blacknum, basenum);
	}
private:
	void rotateL(Node* parent)
	{
		Node* subR = parent->_right;
		Node* subRL = subR->_left;
		Node* pparent = parent->_parent;

		//1.建立subRL与parent之间的关系
		//左子树滑动
		parent->_right = subRL;
		if (subRL) {
			subRL->_parent = parent;
		}

		//2.建立subR和parent之间的关系
		//更新右子树的左子树
		subR->_left = parent;
		parent->_parent = subR;

		//3.建立pparent和subR之间的关系
		//与上一个节点建立连接
		if (parent == _root)
		{
			_root = subR;
			subR->_parent == nullptr;
		}
		else
		{
			subR->_parent = pparent;
			if (parent = pparent->_left) {
				pparent->_left = subR;
			}
			else {
				pparent->_right = subR;
			}
		}
	}
	void rotateR(Node* parent)
	{
		Node* subL = parent->_left;
		Node* subLR = subL->_right;
		Node* pparent = parent->_parent;


		//滑动
		parent->_left = subLR;
		if (subLR) {
			subLR->_parent = parent;
		}

		//更新左子树的右子树
		subL->_right = parent;
		parent->_parent = subL;

		if (parent == _root) {
			_root = subL;
			subL->_parent = nullptr;
		}
		else {
			subL->_parent == pparent;
			if (parent = pparent->_left) {
				pparent->_left = subL;
			}
			else {
				pparent->_right = subL;
			}
		}
	
	}
	
	int _Height(Node* root)
	{
		if (!root) {
			return 0;
		}
		int left = _Height(root->_left);
		int right = _Height(root->_right);

		return left > right ? left + 1 : right + 1;
	}
	bool _IsBalance(Node* root)
	{
		if (root == nullptr)
		{
			return true;
		}
		if (root->_color != Black)
		{
			return false;
		}

		int basenum = 0;
		Node* cur = _root;
		while (cur)
		{
			if (cur->_color == Black) {
				++basenum;
			}
			cur = cur->_left;
		}

		return checkColor(root, 0, basenum);
	}

};

测试代码

#include "RB_tree.h"
#include<vector>

int main()
{
	const int N = 10;
	vector<int> v;
	v.reserve(N);
	srand(time(0));

	for (size_t i = 0; i < N; i++)
	{
		v.push_back(i);
	}

	for (auto i : v)
	{
		cout << i << " ";
	}
	cout << endl;

	RBTree<int, int> rbt;
	for (auto e : v)
	{
		rbt.Insert(make_pair(e, e));
		cout << "Insert:" << e << endl;
	}
	
	cout << rbt.Height() << endl;
	if (rbt.IsBalance())
	{
		cout << "ok" << endl;

	}
	
	return 0;
}

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

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

相关文章

【计算机视觉】Vision Transformers算法介绍合集(一)

文章目录 一、Vision Transformer二、Swin Transformer三、Detection Transformer四、Data-efficient Image Transformer五、self-DIstillation with NO labels六、Deformable DETR七、Compact Convolutional Transformers八、NesT九、Pyramid Vision Transformer十、Dense Pre…

什么是MQ消息队列及四大主流MQ的优缺点(个人网站复习搬运)

什么是&#xff2d;&#xff31;消息队列及四大主流&#xff2d;&#xff31;的优缺点 小程序要上一个限时活动模块&#xff0c;需要有延时队列&#xff0c;从网上了解到用RabbitMQ可以解决&#xff0c;就了解了下 MQ 并以此做记录。 一、为什么要用 MQ 核心就是解耦、异步和…

算法笔记—多数相加

首先&#xff0c;我们要引入一个一道题目1. 两数之和 - 力扣&#xff08;LeetCode&#xff09; 两数之和 其实这道题很简单&#xff0c;但是&#xff0c;可以使用内嵌循环来进行遍历&#xff0c;找到符合要求的数据&#xff0c;返回下标即可。 但今天提供另一个方法&#xff…

劳务管理 视频监控 项目版智慧工地管理系统源码

智慧工地管理系统将人工智能技术、传感器技术、虚拟现实技术等更多高新技术嵌入到建筑、机器、人员佩戴的设备、工地出入口大门等各种物体中&#xff0c;广泛互联形成“物联网技术”&#xff0c;再与“互联网技术”融合&#xff0c;完成项目管理利益相关者与项目施工现场的融合…

数据仓库模型设计V2.0

一、数仓建模的意义 数据模型就是数据组织和存储方法&#xff0c;它强调从业务、数据存取和使用角度合理存储数据。只有将数据有序的组织和存储起来之后&#xff0c;数据才能得到高性能、低成本、高效率、高质量的使用。 高性能&#xff1a;良好的数据模型能够帮助我们快速查询…

考研算法47天:01背包

问题描述 算法详细步骤 代码随想录 (programmercarl.com) ac代码 #include <iostream> using namespace std; int bag[1001]; int bagMax[1001]; int bagvalue[1001]; int main(){int n,v;cin>>n>>v;for(int i0;i<n;i){cin>>bag[i]>>bagva…

跨站脚本攻击实验-beef

实验目的 学习XSS工具/手工攻击的原理掌握XSS工具/手工攻击的方法学习防御XSS的方法/原理 实验工具 burpsuite Burp Suite 是用于攻击web 应用程序的集成平台。它包含了许多工具&#xff0c;并为这些工具设计了许多接口。所有的工具都共享一个能处理并显示HTTP 消息&#xff…

电路电子技术2电容电感伏安关系 计算电路中某两端电压

1.计算电流 思路&#xff1a;可以知道R1两端的电压&#xff0c;即U1&#xff0c;计算出流过R1的电流。接下来计算R2两端的电压&#xff0c;即US-U1&#xff0c;进而知道流过R2的电流。根据在节点处的KCL&#xff0c;即可求出I。 2.电容电感伏安关系 电容元件与电感元件的伏安…

购买问界M7大五座(自动驾驶走进我们的生活一)

龙龙在两天前下了问界M7大五座的大定&#xff08;5000元&#xff09;&#xff0c;今天周末陪幺姨、姨爹、龙龙在重庆汽博问界4S店谈完了M7大五座的订购事宜。 早上10点到店后&#xff0c;姨爹在问界M5上完成了他的第一次自动驾驶试驾。小唐先开了一段路示范自驾&#xff0c;在回…

机器学习(16)---聚类(KMeans)

聚类 一、聚类概述1.1 无监督学习与聚类算法1.2 sklearn中的聚类算法 二、 KMeans2.1 基本原理2.2 簇内误差平方和 三、sklearn中的KMeans3.1 所用模块3.2 聚类算法的模型评估指标3.3 轮廓系数3.4 CHI(卡林斯基-哈拉巴斯指数) 四、KMeans做矢量量化4.1 概述4.2 案例 一、聚类概…

第二节:利用VBA代码交换三个单元格的值

【分享成果&#xff0c;随喜正能量】经常在做一件事时&#xff0c;一开始动力很足&#xff0c;可时间久了&#xff0c;就会出现意志力消耗殆尽。流水不腐&#xff0c;户枢不蠹。做一件对自己好的小事&#xff0c;养一个好习惯&#xff0c;慢慢坚持&#xff0c;持续去做&#xf…

[abc复盘] abc319 20230909

[abc复盘] abc319 20230909 总结A - Legendary Players1. 题目描述2. 思路分析3. 代码实现 B - Measure1. 题目描述2. 思路分析3. 代码实现 C - False Hope1. 题目描述2. 思路分析3. 代码实现 D - Minimum Width1. 题目描述2. 思路分析3. 代码实现 E - Bus Stops1. 题目描述2.…

k8s pod概念、分类及策略

目录 一.pod相关概念 &#xff12;.Kubrenetes集群中Pod两种使用方式 &#xff13;.pause容器的Pod中的所有容器共享的资源 &#xff14;.kubernetes中的pause容器主要为每个容器提供功能&#xff1a; &#xff16;.Pod分为两类&#xff1a; 二.Pod容器的分类 1.基础容器…

第P5周—运动鞋识别

一、前期工作 1.导入数据集 数据集&#xff1a;工作台 - Heywhale.com import torch import matplotlib.pyplot as plt from torchvision import transforms, datasets import os, PIL, random, pathlibdata_dir rD:\P5-data\test data_dir pathlib.Path(data_dir)data_pa…

进程退出、孤儿进程、僵尸进程

进程退出 子进程退出&#xff0c;有些资源需要父进程去释放 /*#include <stdlib.h>void exit(int status);#include <unistd.h>void _exit(int status);status参数&#xff1a; 进程退出的一个状态信息。父进程回收资源的时候可以获取 */#include <stdlib.h>…

【C++】使用红黑树进行封装map和set

&#x1f307;个人主页&#xff1a;平凡的小苏 &#x1f4da;学习格言&#xff1a;命运给你一个低的起点&#xff0c;是想看你精彩的翻盘&#xff0c;而不是让你自甘堕落&#xff0c;脚下的路虽然难走&#xff0c;但我还能走&#xff0c;比起向阳而生&#xff0c;我更想尝试逆风…

【IEEE 13 节点分配系统中的THD降低】系统的谐波分析给出了各种总线上电流和电压的谐波频谱和THD(Simulink实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

phantomjs插件---实现通过链接生成网页截图

Phantomjs | PhantomJS 配置要求 windows下&#xff0c;安装完成phantomJS 设置phantomjs环境变量【也可直接使用phantomjs目录下的执行文件】 直接通过访问php文件执行/通过cmd命令行执行【phantomjs phantom_script.js】 linux下,安装完成phantomJS 设置phantomjs环境变量 直…

模拟实现链式二叉树及其结构学习——【数据结构】

W...Y的主页 &#x1f60a; 代码仓库分享 &#x1f495; 之前我们实现了用顺序表完成二叉树(也就是堆)&#xff0c;顺序二叉树的实际作用就是解决堆排序以及Topk问题。 今天我们要学习的内容是链式二叉树&#xff0c;并且实现链式二叉树&#xff0c;这篇博客与递归息息相关&a…

前端JavaScript中requestAnimationFrame:优化动画和渲染的利器

&#x1f3ac; 岸边的风&#xff1a;个人主页 &#x1f525; 个人专栏 :《 VUE 》 《 javaScript 》 ⛺️ 生活的理想&#xff0c;就是为了理想的生活 ! 目录 引言 1. requestAnimationFrame简介 2. requestAnimationFrame的属性 3. requestAnimationFrame的应用场景 3.1…