【C++】红黑树

本文详细介绍了红黑树的概念、性质,并重点解析了红黑树的插入操作,包括三种特殊情况进行的旋转和颜色调整,帮助读者深入理解红黑树的平衡策略。插入时新节点默认为红色,以避免破坏红黑树的性质。总结了三种插入情况及其解决方法,强调在理解插入逻辑时多画图辅助分析。
摘要由CSDN通过智能技术生成

目录

  1. 红黑树概念
  2. 红黑树性质
  3. 红黑树的定义
  4. 红黑树的插入(重点)
    1. 情况1(违反原因、解决方法、整体图解)
    2. 情况2(情况的产生、解决方法、整体图解、方法判断
    3. 情况3方法判断解决方法、整体图解)
    4. 三种情况的总结
  5. 红黑树的代码实现

讲前小结:红黑树的插入部分理解的时候要多画图,搞清楚不同情况下的插入逻辑。其实画图花多了,理解起来就不是那么的费劲。
本节大部分是图解。红黑树中的红色节点用红色代替,黑色节点用黑色代替

红黑树

红黑树的概念

红黑树,其实就是一种二叉搜索树的优化。每一个节点都会有一个颜色进行标记(红色,或者黑色)。它的五条性质决定它是一种近似平衡的二叉树。

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

我们根据上面五条性质,可以知道红黑树中最主要的性质是:

  1. 红黑树中不会出现连续的红节点(第3条性质)
  2. 每一条路径上的黑色节点的数量相同(第4条性质)

还能由这五条性质可以推出:
红黑树中最长路径中节点个数不会超过最短路径节点个数的两倍
假设每一条路径上有X个黑色节点,红黑树中红色节点,不能连续出现,所以可以穿插在黑色节点,肯定不会破坏性质4. 那么最长的路径就是2x-1. 2x - 1 < 2*x 。所以最长路径中节点的个数不会超过最短路径中节点个数的两倍。

红黑树节点的定义

红黑树是三叉链型的结构。所以每一个节点中都要有三个指针,指向左右子节点和父亲节点

enum Colour //标记红黑树的节点的颜色
{
   
	BLACK,
	RED,
};

// 红黑的节点
template <class T>
struct RBTreeNode
{
   
	RBTreeNode<T>* _left; 
	RBTreeNode<T>* _right;
	RBTreeNode<T>* _parent;

	T _data;   // 节点的值
	Colour _col; // 节点的颜色

	RBTreeNode(const T& data)  //节点的构造函数
		:_left(nullptr)
		, _right(nullptr)
		, _parent(nullptr) 
		, _data(data)
		, _col(RED)
	{
   }
};


红黑树中最重要的步骤就是红黑树的插入

红黑树的插入

红黑树是对二叉搜索数的优化,所以插入节点的要求还是按照二叉搜索树的,小于节点的,插入到左子树,大于节点的,插入到右子树
黑树中由于有五条性质限制,所以我们要考虑插入节点是否破坏了当前的红黑树,而且对于破坏结构的红黑树,还要用 调整红黑树中节点的颜色旋转的方法适当调整红黑树,使红黑树满足五条性质。

我们在插入的时候插入节点选择红色还是黑色?
我们插入的新节点也应该尽量的不破坏红黑树的五条性质。所以我们插入的新节点默认颜色是红色。如果我们插入的节点是黑色,则一定会破坏性质4,使得每一条路径上黑色节点的数目不一样多。 如果我们插入的节点是红色,我们有可能破坏性质3,如果父节点也是红色的,那么我们就对红黑树进行调节。所以插入的时候,默认新节点的颜色是红色

但是插入之后,就有可能违反红黑树的五条性质,破坏红黑树的结构。所以我们要分情况来讨论。

总的特殊情况分为三类
约定cur为当前节点,p为父节点(parent),g为祖父节点(grandparent),u为叔叔节点(uncle)

  • 情况一: cur为红色,parent为红色,grandparent为黑色,uncle存在且为红色

违反原因
插入的cur为红色节点,parent节点也是红色,两个红色节点连在一起,违反了第三条性质,破坏了原本的红黑树结构。

解决方法
将parent节点和uncle节点改成黑色,grandfather节点改为红色。然后把grandfather当成cur,继续向上调整
如下图(cur插入在parent的左右 或者 parent和uncle互换左右都是一样的)

整体图解:
在这里插入图片描述

在这里插入图片描述

注意 :grandparent节点不是根节点,但是当grandparent的上一个节点还是红节点的话,还得继续向上调整。
在这里插入图片描述

  • 情况二:cur为红色,parent为红色,grandparent为黑色,uncle不存在/uncle为黑色
情况二的产生

根据uncle节点的有无,cur节点的又有两种不同的解释(解决的方案都一样,而且弄懂逻辑就很简单了)

  1. 当uncle节点不存在时,则cur一定是新插入的节点,因为每一条路径上的黑色节点个数要相同
    在这里插入图片描述
  2. 当uncle节点存在且黑为色是,cur节点的原来的颜色一定是为黑色的。红色的原因是cur的子树在调整的过程正将cur节点的颜色由黑色改为红色。

在这里插入图片描述
解决方法:
parent为grandparen的左孩子,cur为p的左孩子,则进行右单旋
parent为grandparent的右孩子,cur为p的右孩子,则进行左单旋
parent变成黑色
grandparent变为红色

整体图解:
在这里插入图片描述

情况二判断旋转的方法:

在情况二中,我们可以看到

  1. cur、parent、grandparent都是在一条线上的。
  2. 左边高,将左边压下来,所以进行右单旋。
  3. 右边高,将右边压下来,所以进行左单旋

例如࿱

  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
抱歉,我是一名语言模型AI,无法为您提供演示实时代码功能。但是,我可以向您解释红黑树的基本原理和操作。红黑树是一种自平衡二叉搜索树,它的每个节点都有一个颜色属性,红色或黑色,具有以下特性: 1. 根节点为黑色。 2. 所有叶子节点(NIL节点)为黑色。 3. 如果一个节点为红色,则它的两个子节点必须都为黑色。 4. 从任意一个节点到其每个叶子节点的所有路径都包含相同数量的黑色节点红黑树的基本操作包括插入、删除和查找。插入和删除操作会破坏红黑树的平衡性,需要通过旋转和重新着色来修复平衡。查找操作与二叉搜索树相同,具有O(log n)的时间复杂度。 以下是红黑树的插入操作的伪代码: 1. 新节点插入到红黑树中,颜色为红色。 2. 如果新节点的父节点为黑色,则不需要做任何操作,树仍然平衡。 3. 如果新节点的父节点为红色,需要进行以下操作: (1) 如果新节点的叔节点(父节点的兄弟节点)为红色,则将父节点和叔节点涂黑,祖父节点涂红,然后将当前节点指向祖父节点,重复步骤2。 (2) 如果新节点的叔节点为黑色,并且新节点是父节点的右子节点(父节点为祖父节点的左子节点),则将父节点左旋转,将当前节点指向父节点,重复步骤4。 (3) 如果新节点的叔节点为黑色,并且新节点是父节点的左子节点(父节点为祖父节点的右子节点),则将父节点右旋转,将当前节点指向父节点,重复步骤4。 4. 将父节点涂黑,祖父节点涂红,然后进行以下操作: (1) 如果当前节点是父节点的左子节点,将祖父节点右旋转。 (2) 如果当前节点是父节点的右子节点,将祖父节点左旋转。 以上是红黑树的基本操作,希望能够帮助您理解红黑树的原理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值