【红黑树变色+旋转】

2024-06-07 23:28
文章标签 红黑树 旋转 变色

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

文章目录

  • 一. 红黑树规则
  • 二. 情况一叔叔存在且为红
  • 情况二.变色+旋旋

一. 红黑树规则

对于红黑树,进行变色+旋转处理,终究都是为了维持颜色+以下几条规则,只有颜色和规则维持住了,红黑树就维持住了最长路径的长度不超过最短路径的两倍。

规则:

  1. 根是黑的。
  2. 没有连续的红节点。
  3. 每条路径的黑色数量相等。

二. 情况一叔叔存在且为红

注意点:红黑树插入的节点都是红色的,因为在红黑树中动黑色节点是非常忌讳的,因为要维持每条路径黑色数量相等非常困难,所以插入的节点默认都是红色的。

当插入红色节点后:1.如果父亲为黑或者父亲不存在,结束,不需要任何处理。
2. 如果父亲存在且为红,由于插入节点为红,存在连续红节点,需要处理,可以肯定的是爷爷一定是黑,因为插入节点前就是一棵红黑树了,既然父亲和爷爷颜色确定,主要看叔叔。

1.叔叔存在且为红
在这里插入图片描述
在这里插入图片描述

情况二.变色+旋旋

叔叔存在且为黑或者叔叔不存在都需变色+旋转,关键分析是左单旋,右单旋,还是左右双旋,还是右左双旋只要旋转后,就平衡了,直接结束,不需要向上更新

1. 变色+单旋
在这里插入图片描述
对于叔叔存在且为黑或不存在这种情况,不可能是因为直接插入红色节点导致连续红这种情况直接发生的,因为这发生了,原本就不是红黑树,一定是由上述图一第一种情况处理更新上来导致的。
解决办法:curp->left, pg->left 左左右单旋g点+
p变黑,g变红。
同理:如果上述情况curp->right, pg->right,右右左单旋g点+p变黑,g变红

2.变色+双旋
在这里插入图片描述
对于这种情况:curp->right, pg->left,左右双旋,
将p左旋,g右旋,+ cur变黑+g变红。

同理:curp->left, pg->right, 右左双旋,将p右旋,g左旋,+cur变黑+g变红

总结单纯变色处理,需要不停向上更新至父亲不存在或者父亲为黑结束,旋转+变色处理完就平衡了直接结束。
一下是代码实现

bool Insert(const pair<K, V>& kv){if (_root == nullptr){_root = new Node(kv);_root->_col = BLACK;	//根为黑色return true;}Node* parent = nullptr;Node* cur = _root;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;//父亲存在且为红,连续红节点,处理(如果父亲不存在管你红黑就结束了,如果为黑也结束了)while (parent && parent->_col == RED){Node* grandfather = parent->_parent;  //算出爷爷,根据父亲为爷爷的左右,确定叔叔if (parent == grandfather->_left){Node* uncle = grandfather->_right;//情况一:叔叔存在且为红 变色处理if (uncle && uncle->_col == RED){parent->_col = uncle->_col = BLACK;grandfather->_col = RED;//根节点保证为黑下面处理//继续往上处理cur = grandfather;parent = cur->_parent;}//情况二:叔叔不存在/叔叔存在且为黑else{//需要判别单旋还是左旋,确定cur的位置//旋转+变色if (cur == parent->_left){//		g//	 p		u//c//左左右单旋RotateR(grandfather);parent->_col = BLACK;grandfather->_col = RED;}else{//		g//	p		u//	   c//左右双旋+变色RotateL(parent);RotateR(grandfather);cur->_col = BLACK;grandfather->_col = RED;}break;	//只要旋转结束就平衡了结束}}else{Node* uncle = grandfather->_left;//情况一:叔叔存在且为红 变色处理if (uncle && uncle->_col == RED){parent->_col = uncle->_col = BLACK;grandfather->_col = RED;//根节点保证为黑下面处理//继续往上处理cur = grandfather;parent = cur->_parent;}//情况二:叔叔不存在/叔叔存在且为黑else{if (cur == parent->_right){//		g//	u		p//				cRotateL(grandfather);parent->_col = BLACK;grandfather->_col = RED;}else{//		g//	u		p//		 c//右左双旋RotateR(parent);RotateL(grandfather);cur->_col = BLACK;grandfather->_col = RED;}//只要旋转完了,就平衡结束了break;}}}_root->_col = BLACK;	//变色没有处理根,无论怎么处理都保证根是黑的return true;}void RotateL(Node* parent){++rotateSize;Node* subR = parent->_right;Node* subRL = subR->_left;parent->_right = subRL;if (subRL)subRL->_parent = parent;subR->_left = parent;Node* ppnode = parent->_parent;parent->_parent = subR;if (_root == parent){_root = subR;subR->_parent = nullptr;}else{if (parent == ppnode->_left){ppnode->_left = subR;}else{ppnode->_right = subR;}subR->_parent = ppnode;}}void RotateR(Node* parent){++rotateSize;Node* subL = parent->_left;Node* subLR = subL->_right;parent->_left = subLR;if (subLR)subLR->_parent = parent;subL->_right = parent;Node* ppnode = parent->_parent;parent->_parent = subL;if (parent == _root){_root = subL;subL->_parent = nullptr;}else{if (parent == ppnode->_left){ppnode->_left = subL;}else{ppnode->_right = subL;}subL->_parent = ppnode;}}

无论怎么方式处理完都需要保证根是黑的,最后加上

这篇关于【红黑树变色+旋转】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

Qt QWidget实现图片旋转动画

《QtQWidget实现图片旋转动画》这篇文章主要为大家详细介绍了如何使用了Qt和QWidget实现图片旋转动画效果,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 一、效果展示二、源码分享本例程通过QGraphicsView实现svg格式图片旋转。.hpjavascript

poj 2187 凸包or旋转qia壳法

题意: 给n(50000)个点,求这些点与点之间距离最大的距离。 解析: 先求凸包然后暴力。 或者旋转卡壳大法。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <s

Android 10.0 mtk平板camera2横屏预览旋转90度横屏拍照图片旋转90度功能实现

1.前言 在10.0的系统rom定制化开发中,在进行一些平板等默认横屏的设备开发的过程中,需要在进入camera2的 时候,默认预览图像也是需要横屏显示的,在上一篇已经实现了横屏预览功能,然后发现横屏预览后,拍照保存的图片 依然是竖屏的,所以说同样需要将图片也保存为横屏图标了,所以就需要看下mtk的camera2的相关横屏保存图片功能, 如何实现实现横屏保存图片功能 如图所示: 2.mtk

二维旋转公式

二维旋转公式 ros的tf工具包可以很方便的实现任意坐标系之间的坐标转换。但是,如果只是想简单的测试想法,而又不想编写过于庞杂的代码,考虑自己写二维旋转的函数。而与二维旋转问题对偶的另一个问题便是二维坐标系旋转变换。这两个问题的形式基本一样,只是旋转的角度相差一个负号。就是这个容易搞混,所以做个笔记,以备查用。 1. 二维旋转公式(算法) 而(此文只针对二维)旋转则是表示某一坐标点 ( x

eclipse中相同变量显示变色设置

java文件的设置"Window"-"preferences"-"Java"-"Editor"-"Mark Occurrences"复选框勾选 js文件的设  置"Window"-"preferences"-"web"-"javascript"-"Mark Occurrences"复选框勾选 。

算法复杂度 —— 数据结构前言、算法效率、时间复杂度、空间复杂度、常见复杂度对比、复杂度算法题(旋转数组)

目录 一、数据结构前言 1、数据结构 2、算法 3、学习方法 二、 算法效率 引入概念:算法复杂度  三、时间复杂度 1、大O的渐进表示法 2、时间复杂度计算示例  四、空间复杂度 计算示例:空间复杂度 五、常见复杂度对比 六、复杂度算法题(旋转数组) 1、思路1 2、思路2 3、思路3 一、数据结构前言 1、数据结构         数据结构(D

计算几何之向量旋转

实际做题中我们可能会遇到很多有关及计算几何的问题,其中有一类问题就是向量的旋转问题,下面我们来具体探讨一下有关旋转的问题。 首先我们先把问题简化一下,我们先研究一个点绕另一个点旋转一定角度的问题。已知A点坐标(x1,y1),B点坐标(x2,y2),我们需要求得A点绕着B点旋转θ度后的位置。 A点绕B点旋转θ角度后得到的点,问题是我们要如何才能得到A' 点的坐标。(向逆时针方向旋转角度正,

红黑树的旋转

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

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

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

yolov8-obb旋转目标检测onnxruntime和tensorrt推理

onnxruntime推理 导出onnx模型: from ultralytics import YOLOmodel = YOLO("yolov8n-obb.pt") model.export(format="onnx") onnx模型结构如下: python推理代码: import cv2import mathimport numpy as npimport onnxr