【数据结构】红黑树的删除(抽丝剥茧,带你理清每一种情况)

这篇具有很好参考价值的文章主要介绍了【数据结构】红黑树的删除(抽丝剥茧,带你理清每一种情况)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

 红黑树的删除,较AVL树的删除比较抽象,同时也跟红黑树的插入的区别较大,但大体上的思路还是基于普通二叉搜索树的基础上进行讨论的。

浅浅的铺垫一下:

  1. 需要清楚普通二叉树的删除,可见AVL树的删除文章开头。
  2. 四种旋转的操作(只需操作)得熟记于心,可见AVL树的插入与验证
  3. 红黑树的插入的变色原理得清楚,可见红黑树的插入与验证

正文

1.所删除的结点为红色

  • 红色的删除最为简单,因为红色结点所连接的结点都是黑色!

为了便于描述,我们这里将所删除的结点称之为delnode

1.1delnode的左右都为空

红黑树删除,数据结构,数据结构,红黑树的插入

不管delnode在左边还是在右边,我们只需要改变父节点的delnode指向为空即可。

1.2delnode的左为空,且右不为空

  • 如果delnode右不为空,则其右为黑色,但是每条路径的黑色结点数必然相同,则delnode的左结点必然也为黑色,与条件的左为空相悖,因此情况不存在

1.3delnode的左不为空,右为空

  • 如果delnode左不为空,则其左为黑色,但是每条路径的黑色结点数必然相同,则delnode的右结点必然也为黑色,与条件的右为空相悖,因此情况不存在

1.4delnode的左不为空,且右不为空

  • 根据普通二叉搜索树,这里要找左子树的最大结点,进行值交换,然后再删除找到的左子树的最大节点,其如果为红色,则转换为1.1情况。

  • 因此:delnode为红色只有一种处理方法。

2.所删除的结点为黑色

  • 重头戏来了!
    为了便于描述,我们这里将所删除的结点称之为delnode

 先对delnode进行分析,既然为黑色,其左节点或者右节点为红色,或者左右结点都为红色,或者左右都为空,当然分析到这里还不够,我们还要对其uncle进行分析。

2.1 调整后所在树每条路径黑色结点的个数不发生变化

2.1 左结点不为空,右节点为空
  • 左节点只能是红色,因为每条路径的黑色结点数是一样的。
    红黑树删除,数据结构,数据结构,红黑树的插入

不管delnode为parent的左结点还是右节点,parent的指向delnode的节点改为指向delnode的左边,再将delnode的左边结点颜色改为黑色即可。

2.2 左结点为空,右节点不为空

红黑树删除,数据结构,数据结构,红黑树的插入

不管delnode为parent的左结点还是右节点,parent的指向delnode的节点改为指向delnode的右节点,再将delnode的右边结点颜色改为黑色即可。

2.3 左右结点都为空

parentdelnode的父节点,父节点另一个链接的结点设为uncle
 如果下面分析delnode结点为左右有些太冗余了,我们只分析cur(delnode)为parent的左结点这一种情况,最后cur为parent右结点这一种情况,最后以图解的方式呈现。

2.3.1 uncle为黑色
2.3.1.1uncle的左节点为红色(右不为红)
  1. 父节点为红色
  • uncle右节点为黑色

此情况为delnode向上迭代的一种情况:
红黑树删除,数据结构,数据结构,红黑树的插入

  • uncle右节点为空

此时:cur为delnode/向上迭代的一种情况。
红黑树删除,数据结构,数据结构,红黑树的插入

  1. 父节点为黑色
  • uncle右节点为黑色

此情况为delnode向上迭代的一种情况。
红黑树删除,数据结构,数据结构,红黑树的插入

  • uncle右节点为空
    此情况为:cur为delnode
    红黑树删除,数据结构,数据结构,红黑树的插入

 总结分析方式是一样的,只是最后实际的变色是不一样的,我们可以从中发现一个变色规律:

  1. 右左双旋
  2. uncle_left赋值为黑色
2.3.1.2uncle的右节点为红色
  1. 父节点为黑色
  • uncle的左节点为黑色
    红黑树删除,数据结构,数据结构,红黑树的插入

  • uncle的左节点为红色

红黑树删除,数据结构,数据结构,红黑树的插入

  1. 父节点为红色
  • uncle的左节点为黑色

红黑树删除,数据结构,数据结构,红黑树的插入

  • uncle的左节点为红色

红黑树删除,数据结构,数据结构,红黑树的插入

 总结分析方式是一样的,只是最后实际的变色是不一样的,我们可以从中发现一个变色规律:

  1. 左旋
  2. parent的颜色赋值给uncle
  3. parent的颜色与uncle_right的颜色赋值为黑色
2.3.1.3uncle的左右结点都为黑色
  • parent为红色

红黑树删除,数据结构,数据结构,红黑树的插入

2.3.2 uncle红色
  • uncle为红色,其连接的结点必然为黑色,又因为delnode为黑,所以uncle的左右结点必然存在。
2.3.2.1 uncle的左右结点都为黑

红黑树删除,数据结构,数据结构,红黑树的插入

整棵树每条路径的黑色结点数不变,但是此时cur的uncle更新为un_left为黑色,继续对uncle的情况进行判断即可,更新后parent为红且uncle为黑,一定是高度不变化的一种情况之一,再判断一次即可。

2.2 调整后所在树每条路径黑色结点的个数发生变化

parentdelnode的父节点,父节点另一个链接的结点设为uncle

2.2.1 uncle为黑色
  • 上面uncle为黑色且高度不变化的情况已经考虑过了,这里只剩下一种情况。
2.2.1.1 uncle的左右结点为黑色
  • parent为黑色
    红黑树删除,数据结构,数据结构,红黑树的插入

整棵树每条路径的黑色结点数少一个,继续向上调整,cur等于parent,parent更新为cur的parent,最坏情况到根节点结束。

图解

红黑树删除,数据结构,数据结构,红黑树的插入

实现代码

void ChangeColor(Node* cur,Node* parent)
{
	while (parent)
	{
		if (parent->_left == cur)
		{
			Node* uncle = parent->_right;
			//既然cur为黑结点,那么uncle就必然不可能为空。
			if (uncle->_col == RED)
			{
				//父节点必然为黑结点,uncle的左右孩子必然为黑色结点。

				//进行左旋
				RotateL(parent);
				uncle->_col = BLACK;
				parent->_col = RED;

				//无需更新。
			}
			else
			{
				//再次强调uncle是不可能为空的,因为cur为黑色结点。

				//需要对uncle的左右孩子进行判断
				Node* un_right = uncle->_right;
				Node* un_left = uncle->_left;
				//un_right 与 un_left可能为空。
				// 
				//uncle的左结点为红色,右节点为黑色或者为空
				if (un_left && un_left->_col == RED 
				&& (un_right == nullptr || un_right->_col == BLACK))
				{
					//先变色
					uncle->_col = RED;
					un_left->_col = BLACK;
					//进行右旋
					RotateR(uncle);

				}
				//uncle的右节点为红色,uncle的左节点为黑色或者红色或者为空
				else if (un_right && un_right->_col == RED)
				{
					//先变色
					uncle->_col = parent->_col;
					parent->_col = un_right->_col = BLACK;
					//进行左旋
					RotateL(parent);

					//到此处达到平衡
					break;
				}
				//uncle的左节点为黑色且右节点也为黑色。
				else
				{
					//直接进行变色
					uncle->_col = RED;
					if (parent->_col == BLACK)
					{
						//更新cur结点与parent结点,继续向上更新。
						cur = parent;
						parent = cur->_parent;
					}
					else//父节点为红色
					{
						//变父节点为黑色,跳出循环。
						parent->_col = BLACK;
						break;
					}
				}
			}

		}
		else
		{
			Node* uncle = parent->_left;

			//uncle结点为红色
			if (uncle->_col == RED)
			{
				//变色保证路径的黑色结点的个数不变。
				//此时新更新的uncle的颜色变为黑色。
				uncle->_col = BLACK;
				parent->_col = RED;
				//父节点,un_left与un_right皆为黑色。
				RotateR(parent);
			}
			else
			{
				//uncle结点为黑色
				Node* un_right = uncle->_right;
				Node* un_left = uncle->_left;
				//uncle的右节点为红色,且左节点为黑色或者空
				if (un_right && un_right->_col == RED &&\
				 (un_left == nullptr || un_left->_col == BLACK))
				{

					//变色保证路径的黑色结点数不发生变化
					uncle->_col = RED;
					un_right->_col = BLACK;
					//以uncle结点进行进行左旋,此时un_right成uncle
					RotateL(uncle);

				}
				//uncle的左节点为红色,且右节点为黑/红/空。
				else if (un_left && un_left->_col == RED)
				{
					//先变色保证路径的黑色结点数不发生变化
					uncle->_col = parent->_col;
					parent->_col = un_left->_col = BLACK;
					//进行右旋
					RotateR(parent);
					break;
				}
				//uncle的左右结点都为黑色
				else
				{
					uncle->_col = RED;
					if (parent->_col == BLACK)
					{
						cur = parent;
						parent = cur->_parent;
					}
					else
					{
						parent->_col = BLACK;
						break;
					}
				}
			}

		}
	}
}

总结

  • 理解的难点
  1. 分类讨论,逐步分析,拆解与转换问题
  2. 旋转与变色的底层逻辑是增加待删除路径的黑色结点数,同时保证另一棵树的每一条路径的黑色结点数不发生变化,结果是树的每条黑色结点的路径数不变
  3. 时间与耐心

 博主认为这三点缺一不可。

 红黑树的删除比插入是难了不少的,不像AVL树的删除,可以复用之前的轮子,这里还得重新分析,每一种情况,博主看网上的大多数的讲解是比较抽象的,所以这里特意举了很多实际的例子进行分析,希望能降低一些红黑树插入的难度。

最后如果本篇文章对您有所帮助的话,不妨点个赞鼓励一下吧!文章来源地址https://www.toymoban.com/news/detail-860180.html

到了这里,关于【数据结构】红黑树的删除(抽丝剥茧,带你理清每一种情况)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 数据结构之进阶二叉树(二叉搜索树和AVL树、红黑树的实现)超详细解析,附实操图和搜索二叉树的实现过程图

    绪论​ “生命有如铁砧,愈被敲打,愈能发出火花。——伽利略”;本章主要是数据结构 二叉树的进阶知识,若之前没学过二叉树建议看看这篇文章一篇掌握二叉树,本章的知识从浅到深的 对搜索二叉树的使用进行了介绍和对其底层逻辑的实现进行了讲解 ,希望能对你有所

    2024年02月04日
    浏览(47)
  • 数据结构 | 红黑树

    节点的左边比节点的值小,右边比节点的值大。 节点要么是 红色 ,要么是 黑色 根节点 是黑色 叶子节点都是黑色的空节点 红黑树中红色节点的子节点都是黑色 从任一节点到叶子节点的所有路径都包含相同数目的黑色节点 在添加或者删除节点的时候,如果不满足这些性质会

    2024年01月21日
    浏览(44)
  • [数据结构]-红黑树

    前言 作者 : 小蜗牛向前冲 名言: 我可以接受失败,但我不能接受放弃   如果觉的博主的文章还不错的话,还请 点赞,收藏,关注👀支持博主。如果发现有问题的地方欢迎❀大家在评论区指正 目录 一、红黑树的基本知识  1、红黑树的概念 2、性质  二、红黑树的模拟实

    2024年02月04日
    浏览(46)
  • 【数据结构】红黑树

    🐱作者:一只大喵咪1201 🐱专栏:《数据结构与算法》 🔥格言: 你只管努力,剩下的交给时间! 在学习AVL树的时候,我们知道,当修改AVL树的结构(插入,删除)时,会通过旋转来保证平衡因子不超过1,所以频繁的修改结构会导致效率低下,今天我们学习的红黑树就完美解

    2023年04月17日
    浏览(49)
  • 数据结构——红黑树

    目录 概念 性质 结点的定义  插入 调整 当p是g的左孩子时 当p为g的右孩子时 插入完整代码 红黑树的检测 红黑树完整代码(包括测试数据)   红黑树,是一种二叉搜索树,但在每个结点上增加一个存储位表示结点的颜色,可以是RED或BLACK。 通过对任何一条从根到叶子的路径

    2023年04月09日
    浏览(46)
  • 【数据结构-树】红黑树

    💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kuan 的首页,持续学习,不断总结,共同进步,活到老学到老 导航 檀越剑指大厂系列:全面总

    2024年02月07日
    浏览(44)
  • 红黑树数据结构

    现在JAVASE中HashMap中底层源码是由数组+链表+红黑树进行设计的,然后很多地方也是用到红黑树,这里单独对红黑树数据结构进行简单的介绍。 目录 红黑树概念 红黑树的性质 自平衡规则 代码   红黑树,是一种二叉搜索树,但在每个结点上增加一个存储位表示结点的颜色,可

    2024年02月01日
    浏览(40)
  • C++数据结构--红黑树

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

    2024年02月09日
    浏览(49)
  • 数据结构入门-11-红黑树

    史上最负盛名的平衡二叉树–红黑树,但其实就是2-3树的一种实现 也是BST,每一个节点都有颜色 性质 看 后面推导出来的结论 2-3树 :和红黑树是等价的 满足BST的基本性质,但不是一种二叉树 有两种节点: 2-3 绝对平衡:根节点到叶子节点 一定相同 2.3.1 如何维护绝对平衡

    2023年04月17日
    浏览(41)
  • 数据结构之红黑树

    数据结构可视化演示链接,也就是图片演示的网址 数据结构之AVL Tree 数据结构之B树和B+树 数据结构之Radix和Trie 数据结构之二叉搜索树 红黑树是一种二叉查找树,但在每个结点上增加了一个存储位表示结点的颜色,可以是RED或者BLACK。通过对任何一条从根到叶子的路径上各个

    2024年01月17日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包