1.红黑树的概念
红黑树是一棵二叉搜索树,他的每个结点增加一个存储位来表示结点的颜色,可以是红色或者黑色。
通过对任何一条从根到叶子的路径上各个结点的颜色进行约束,红黑树确保没有一条路径会比其他路径长出2倍,因而是接近平衡的。
1.1 红黑树的规则:
红黑树的一切都是围绕这4点构建的:
1.每个结点不是红色就是黑色
2.根结点是黑色的
3.如果一个结点是红色的,则它的两个孩子结点必须是黑色的,也就是说任意一条路径不会有连续的红色结点。
4.对于任意一个结点,从该结点到其所有NULL结点的简单路径上,均包含相同数量的黑色结点
只要满足上面4点条件 就一定会有:没有一条路径 会 比其他路径 长出2倍以上。
理论相差最长路径:
右边最多为四个节点,左边最少两个节点。
理论最长路径:比如:
2.红黑树的插入(我们只需要学会这个就行,结尾有总代码)
我们先按照二叉搜索树的规则插入节点:
新增结点标识为c (cur),c的父亲标识为p(parent),p的父亲标识为g(grandfather),p的兄弟标识为u(uncle)。
我们可以分为两大类:
1.第一大类:
叔叔(uncle)存在,并且叔叔(uncle)为红。
这种情况我们只需要变色 + 向上处理,就可以了:
把parent 和 uncle 变为黑色, 把 grandfather 变为红色
再把 cur 变为 grandfather 继续向上更新。
代码为:
3. 第二大类 :
叔叔(uncle)不存在 或者 叔叔(uncle)为黑色
第二大类分为两个小类:
3.1第二大类的第一小类:
这里我们统一以左子树为例子(右子树同理)
1.cur 插入 在 parent 的左边
如图所示:
假设我们 没插入节点之前 的树 如图所示:
插入 cur 节点:
插入后,按照第一大类调整:
把 parent 变黑 , 把 grandfather 变红 ,再把 grandfather 进行右旋转
代码为:
问题:为什么不需要向上更新了(parent如上图)?
没有连续的红色结点了,且不需要往上更新,因为:父亲(parent)是黑色,上面的节点无论是红色或者空都不违反规则。
3.2第二大类的第二小类:
我们统一以左子树为例子(右子树同理)
1.cur 插入在 parent 的 右边 如图所示:
原图
cur 是按 第一大类 更新上来的:
我们以 parent作为旋转点 进行左旋转,再以 grandfather作为旋转点 进行右旋转,最后把 cur变为黑色,grandfather 变为红。
问题:为什么不需要向上更新了(cur如上图)?
没有连续的红色结点了,且不需要往上更新,因为:cur 是黑色,上面的节点无论是红色或者空都不违反规则。
总代码:
bool Insert(const T& data)
{
Node* cur = _pHead;
Node* parent = nullptr;
if (cur == nullptr)
{
_pHead = new Node(data);
}
else
{
while (cur)
{
if (cur->_k < data)
{
parent = cur;
cur = cur->_pRight;
}
else if (cur->_k > data)
{
parent = cur;
cur = cur->_pLeft;
}
else
{
assert(false);
}
}
cur = new Node(data);
if (cur->_k < parent->_k)
parent->_pLeft = cur;
else
parent->_pRight = cur;
cur->_parent = parent;
//上方为插入节点
/
while (parent && parent->cl == RED)
{
Node* uncle = nullptr;
Node* grandfather = parent->_parent;
//左边
if (grandfather && parent == grandfather->_pLeft)
{
uncle = grandfather->_pRight;
if (uncle && uncle->cl == RED)
{
parent->cl = BLACK;
uncle->cl = BLACK;
grandfather->cl = RED;
}
else
{
if (cur == parent->_pLeft)
{
RotateR(grandfather);
parent->cl = BLACK;
grandfather->cl = RED;
}
else
{
RotateL(parent);
RotateR(grandfather);
grandfather->cl = RED;
cur->cl = BLACK;
}
break;
}
cur = grandfather;
parent = cur->_parent;
}
//右边
else if (grandfather && parent == grandfather->_pRight)
{
uncle = grandfather->_pLeft;
if (uncle && uncle->cl == RED)
{
parent->cl = BLACK;
uncle->cl = BLACK;
grandfather->cl = RED;
}
else
{
if (cur == parent->_pRight)
{
parent->cl = BLACK;
grandfather->cl = RED;
RotateL(grandfather);
}
else
{
grandfather->cl = RED;
cur->cl = BLACK;
RotateR(parent);
RotateL(grandfather);
}
}
cur = grandfather;
parent = cur->_parent;
}
}
}
_pHead->cl = BLACK;
return true;
}
左右单旋:
// 左单旋
void RotateL(Node * pParent)
{
Node* RChild = pParent->_pRight;
Node* RLChild = RChild->_pLeft;
Node* grandfather = pParent->_parent;
if (RLChild)
RLChild->_parent = pParent;
pParent->_pRight = RLChild;
RChild->_pLeft = pParent;
pParent->_parent = RChild;
RChild->_parent = grandfather;
if (grandfather == nullptr)
{
_pHead = RChild;
}
else
{
if (grandfather->_pLeft == pParent)
grandfather->_pLeft = RChild;
else if (grandfather->_pRight == pParent)
grandfather->_pRight = RChild;
}
}
// 右单旋
void RotateR(Node * pParent)
{
Node* LChild = pParent->_pLeft;
Node* LRChild = LChild->_pRight;
Node* grandfather = pParent->_parent;
if (LRChild)
LRChild->_parent = pParent;
pParent->_pLeft = LRChild;
LChild->_pRight = pParent;
pParent->_parent = LChild;
LChild->_parent = grandfather;
if (grandfather == nullptr)
{
_pHead = LChild;
}
else
{
if (grandfather->_pLeft == pParent)
grandfather->_pLeft = LChild;
else if (grandfather->_pRight == pParent)
grandfather->_pRight = LChild;
}
}