1. 红黑树的概念
红黑树是一棵二叉搜索树,它在每一个结点上增加了一个存储位来标记结点的颜色,可以是red 或者 black。
2. 红黑树的性质
(1)每个结点不是红色就是黑色
(2)树的根节点是黑色的
(3)没有两个连续的红色结点
(4)对于每个结点,从该节点到所有后代叶结点的简单路径上,均包含相同数目的黑色结点。
3. 红黑树的插入
首先,我们规定新插入的结点是红色。在插入新结点后,可能会破坏红黑树的性质,此时,我们就需要对树进行调整。
红黑树的插入分为5种情况:
(1)如果树为空,插入结点后会破坏性质2,此时,需要将颜色改为黑色。
(2)插入结点的父节点为黑色,不违反任何性质,直接插入。
(3)插入结点cur 为红色,pParent为红色,grandfather为黑色,uncle结点存在且为红色。
解决方法:将pParent结点 和 uncle结点改为黑色,grandfather结点改为红色,将cur=grandfather再向上调整。
(4)插入结点cur为红色,pParent为红色,grandfather为黑色,uncle结点不存在或者为黑色。
解决方法:如果cur为pParent的左子树,pParent为grandfather的左子树,进行右旋;如果cur为pParent的右子树,pParent为grandfather的右子树,进行左旋;
再将pParent结点黑色,grandfather结点改为红色。
(5)插入结点cur为红色,pParent为红色,grandfather为黑色,uncle结点不存在或者为黑色。
解决方法:如果cur为pParent的右子树,pParent为grandfather的左子树,进行左旋;如果cur为pParent的左子树,pParent为grandfather的右子树,进行右旋;交换pParent和cur结点。
即转化为情况(4)处理。
整体代码如下:
bool InsertNode(const K& key, const V& value, COLOR color=RED)
{
if (_PRoot == NULL)
{
_PRoot = new Node(key, value);
_PRoot->_color = BLACK;
return true;
}
PNode Pcur = _PRoot;
PNode pParent = NULL;
while (Pcur)
{
if (key < Pcur->_key)
{
pParent = Pcur;
Pcur = Pcur->_PLeft;
}
else if (key>Pcur->_key)
{
pParent = Pcur;
Pcur = Pcur->_PRight;
}
else
{
return false;
}
}
Pcur = new Node(key, value);
if (pParent->_key > key)
pParent->_PLeft = Pcur;
else
pParent->_PRight = Pcur;
Pcur->_Pparent = pParent;
while (_PRoot!=Pcur && pParent->_color==RED)
{
PNode grandFather = pParent->_Pparent;
if (pParent == grandFather->_PLeft)
{
PNode uncle = pParent->_PRight;
if (uncle && uncle->_color == RED)//情况三
{
pParent->_color = BLACK;
uncle->_color = BLACK;
grandFather->_color = RED;
Pcur = Pcur->_Pparent->_Pparent;
}
else
{
if (Pcur == pParent->_PRight)//情况五
{
RotateL(pParent);
swap(pParent, Pcur);
}
pParent->_color = BLACK;
grandFather->_color = RED;
RotateR(grandFather);
}
}
else
{
PNode uncle = grandFather->_PLeft;
if (uncle && uncle->_color == RED)
{
uncle->_color = BLACK;
pParent->_color = BLACK;
grandFather->_color = RED;
Pcur = Pcur->_Pparent->_Pparent;
}
else
{
if (Pcur == pParent->_PLeft)
{
RotateR(pParent);
swap(pParent, Pcur);
}
pParent->_color = BLACK;
grandFather->_color = RED;
RotateL(grandFather);
}
break;
}
}
_PRoot->_color = BLACK;
return true;
}
void RotateL(PNode pParent)
{
PNode subR = pParent->_PRight;
PNode subRL = subR->_PLeft;
pParent->_PRight = subRL;
if (subRL)
subRL->_Pparent = pParent;
subR->_PLeft = pParent;
PNode ppParent = pParent->_Pparent;
pParent->_Pparent = subR;
subR->_Pparent = ppParent;
if (_PRoot == pParent)
_PRoot = subR;
else
{
if (ppParent->_PLeft == pParent)
ppParent->_PLeft = subR;
else
ppParent->_PRight = subR;
}
}
void RotateR(PNode pParent)
{
PNode subL = pParent->_PLeft;
PNode subLR = subL->_PRight;
pParent->_PLeft = subLR;
if (subLR)
subLR->_Pparent = pParent;
subL->_PRight = pParent;
PNode ppParent = pParent->_Pparent;
pParent->_Pparent = subL;
subL->_Pparent = ppParent;
if (_PRoot == pParent)
_PRoot = subL;
else
{
if (ppParent->_PLeft == pParent)
ppParent->_PLeft = subL;
else
ppParent->_PRight = subL;
}
}
4. 红黑树的查找平均长度
平均查找长度ASL=log N;
插入的时间复杂度 O(log N);