了解红黑树:高效平衡二叉搜索树

红黑树的概念

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

红黑树的性质

  1. 每个结点不是红色就是黑色
  2. 根节点是黑色的
  3. 如果一个节点是红色的,则它的两个孩子结点是黑色的
  4. 对于每个结点,从该结点到其所有后代叶结点的简单路径上,均 包含相同数目的黑色结点
  5. 每个叶子结点都是黑色的(此处的叶子结点指的是空结点)
    这些性质确保了红黑树的平衡性,从而限制了树的高度,使得基本操作的时间复杂度保持在 O(logn)。

思考:为什么满足上面的性质,红黑树就能保证:其最长路径中节点个数不会超过最短路径节点个数的两倍?

  1. 性质分析

    • 性质1性质3确保了红色节点不会相邻,且红色节点的子节点必须是黑色的。这有助于限制红色节点在树中的分布,从而限制树的高度增长。
    • 性质2性质5指出根节点和叶子节点(空节点)都是黑色的,这提供了一个基本的黑色节点数量标准。
    • 性质4是红黑树保持平衡的关键。它确保了从根到任何叶子节点的所有简单路径上,黑色节点的数量是相同的。这意味着树的高度是固定的,而红色节点只是在这个基础上增加了额外的层。
  2. 路径长度分析

    • 假设从根到叶子的最长路径上,黑色节点的数量为h
    • 由于红色节点不能相邻,且每个红色节点下面至少有两个黑色节点(其子节点),因此最长路径(包含红色和黑色节点)上红色节点的数量最多为h-1(因为根是黑色的,所以路径开始时不计算红色节点)。
    • 因此,最长路径上的节点总数最多为2h - 1h个黑色节点加上最多h-1个红色节点)。
    • 最短路径(全为黑色节点)上的节点数量为h
  3. 最长路径与最短路径的比较

    • 最长路径上的节点数2h - 1与最短路径上的节点数h的比值为(2h - 1) / h,简化后为2 - 1/h
    • 由于h是整数且h >= 1(因为至少有一个黑色节点,即根节点),所以1/h的值在(0, 1]范围内。
    • 因此,(2 - 1/h)的值总是小于或等于2,即最长路径上的节点数不会超过最短路径节点数的两倍。

红黑树节点的定义

// 节点的颜色
enum Color{RED, BLACK};
// 红黑树节点的定义
template<class ValueType>
struct RBTreeNode
{
	 RBTreeNode(const ValueType& data = ValueType(),Color color = RED)
	     : _pLeft(nullptr), _pRight(nullptr), _pParent(nullptr)
	     , _data(data), _color(color)
	 {}
	 RBTreeNode<ValueType>* _pLeft;   // 节点的左孩子
	 RBTreeNode<ValueType>* _pRight;  // 节点的右孩子
	 RBTreeNode<ValueType>* _pParent; // 节点的双亲(红黑树需要旋转,为了实现简单给出该字段)
	 ValueType _data;            // 节点的值域
	 Color _color;               // 节点的颜色
};

思考:在节点的定义中,为什么要将节点的默认颜色给成红色的?

不能有两个连续的红色节点。如果我们将新插入的节点默认设置为黑色,那么插入操作可能会导致树中违反这一性质的情况。通过将新节点设置为红色,我们可以更方便地进行调整,而不会破坏树的黑色节点平衡。

插入操作

在红黑树中插入节点的过程分为两个步骤:

标准二叉搜索树插入:首先按照二叉搜索树的插入规则将新节点插入树中,并将新节点着色为红色。
调整树:通过颜色翻转和旋转操作来恢复红黑树的性质。
以下是插入操作的详细步骤:

  1. 按照二叉搜索的树规则插入新节点
  2. 检测新节点插入后,红黑树的性质是否造到破坏
    因为新节点的默认颜色是红色,因此:如果其双亲节点的颜色是黑色,没有违反红黑树任何性质,则不需要调整;但当新插入节点的双亲节点颜色为红色时,就违反了性质三不能有连在一起的红色节点,此时需要对红黑树分情况来讨论:

约定:cur为当前节点,p为父节点,g为祖父节点,u为叔叔节点

情况一: cur为红,p为红,g为黑,u存在且为红

在这里插入图片描述

情况二: cur为红,p为红,g为黑,u不存在/u存在且为黑

在这里插入图片描述
p为g的左孩子,cur为p的左孩子,则进行右单旋转;相反,
p为g的右孩子,cur为p的右孩子,则进行左单旋转
p、g变色–p变黑,g变红

情况三: cur为红,p为红,g为黑,u不存在/u存在且为黑

在这里插入图片描述
p为g的左孩子,cur为p的右孩子,则针对p做左单旋转;相反,
p为g的右孩子,cur为p的左孩子,则针对p做右单旋转
则转换成了情况2
针对每种情况进行相应的处理即可。

  • 9
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一岁就可帅-

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值