红黑树首先是一棵二叉查找树,它每个结点都被标上了颜色(红色或黑色),红黑树满足以下5个性质:
1、 每个结点的颜色只能是红色或黑色。
2、 根结点是黑色的。
3、每个叶子结点都带有两个空的黑色结点(被称为黑哨兵),如果一个结点n的只有一个左孩子,那么n的右孩子是一个黑哨兵;如果结点n只有一个右孩子,那么n的左孩子是一个黑哨兵。
4、 如果一个结点是红的,则它的两个儿子都是黑的。也就是说在一条路径上不能出现相邻的两个红色结点。
5、对于每个结点来说,从该结点到其子孙叶结点的所有路径上包含相同数目的黑结点。
这些约束强制了红黑树的关键性质: 从根到叶子的最长的可能路径不多于最短的可能路径的两倍长。结果是这个树大致上是平衡的。因为操作比如插入、删除和查找某个值的最坏情况时间都要求与树的高度成比例,这个在高度上的理论上限允许红黑树在最坏情况下都是高效的,而不同于普通的二叉查找树。
要知道为什么这些特性确保了这个结果,注意到性质4导致了路径不能有两个毗连的红色节点就足够了。最短的可能路径都是黑色节点,最长的可能路径有交替的红色和黑色节点。因为根据性质5所有最长的路径都有相同数目的黑色节点,这就表明了没有路径能多于任何其他路径的两倍长。
红黑树上结点的插入
注意:cur为当前节点,p为父节点,g为祖父节点,u为叔叔节点
【情况一】 cur为红,p为红,g为黑,u存在且为红 则将p,u改为黑,g改为红,然后把g当成cur,继续向上调整。
【情况二】 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
代码如下:
#include<iostream>
using namespace std;
enum COLOR{RED, BLACK};
template<class K, class V>
struct RBTreeNode
{
RBTreeNode(const K& key, const V& value, const COLOR& color = RED)
: _pLeft(NULL)
, _pRight(NULL)
, _pParent(NULL)
, _key(key)
, _value(value)
, _color(color)
{}
RBTreeNode<K, V>* _pLeft;
RBTreeNode<K, V>* _pRight;
RBTreeNode<K, V>* _pParent;
K _key;
V _value;
COLOR _color;
};
template<class K, class V>
class RBTree
{
typedef RBTreeNode<K, V> Node;
public:
RBTree()
: _pRoot(NULL)
{}
bool Insert(const K& key, const V& value)
{
//判断树是否存在
if(_pRoot == NULL)
{
_pRoot = new Node(key, value, BLACK);
return true;
}
//找插入位置
Node* pCur = _pRoot;
Node* parent = NULL;
while(pCur)
{
if(key > pCur->_key)
{
parent = pCur;
pCur = pCur->_pRight;
}
else if(key < pCur->_key)
{
parent = pCur;
pCur = pCur->_pLeft;
}
else
return false;
}
//插入节点
pCur = new Node(key, value);
if(key > parent->_key)
parent->_pRight = pCur;
else
parent->_pLeft = pCur;
pCur->_pParent = parent;
Node* pGrangFather = parent->_pParent;
有可能违反红黑树性质
while(pCur != _pRoot && parent->_color == RED)
{
//双亲的双亲一定存在,且为黑色
if(parent == pGrangFather->_pLeft)
{
Node* pUncle = pGrangFather->_pRight;
//情况一:pCur为红色,parent为红色,grand为黑色,uncle为红色
if(pUncle && pUncle->_color == RED )
//uncle存在且为红
{
parent->_color = BLACK;
pUncle->_color = BLACK;
pGrangFather->_color = RED;
pCur = pGrangFather;
parent = pGrangFather->_pParent;
}
//uncle不存在或者uncle存在且为黑色
else
{
//情况三:pCur为parent的右孩子
if(parent->_pRight == pCur)
{
_RotateL(parent);
swap(pCur, parent);
}
//情况二:pCur为parent的左孩子
parent->_color = BLACK;
pGrangFather->_color = RED;
_RotateR(pGrangFather);
}
}
else
{
Node* pUncle = pGrangFather->_pLeft;
//情况一:uncle存在而且uncle为红色
if(pUncle && pUncle->_color == RED)
{
parent->_color = BLACK;
pUncle->_color = BLACK;
pGrangFather->_color = RED;
pCur = pGrangFather;
parent = pGrangFather->_pParent;
}
//uncle不存在或者uncle存在且为黑色
else
{
//情况三:pCur为parent的左孩子
if(pCur == parent->_pLeft)
{
_RotateR(parent);
swap(parent, pCur);
}
//情况二:pCur为parent的左孩子
parent->_color = BLACK;
pGrangFather->_color = RED;
_RotateL(pGrangFather);
}
}
}
_pRoot->_color = BLACK;
return true;
}
void InOrder()
{
cout<<" InOrder: ";
_InOrder(_pRoot);
cout<<endl;
}
bool CheckRBTree()
{
//判断是否满足红黑树
if(_pRoot == NULL)
return true;
if(_pRoot->_color == RED)
{
cout<<"根结点是红色的,不满足性质二"<<endl;
return false;
}
size_t count = 0;
Node* pCur = _pRoot;
while (pCur)
{
if (pCur->_color == BLACK)
count++;
pCur = pCur->_pLeft;
}//统计最左边路径上得黑色结点数
size_t num = 0;
return CheckColour(_pRoot) && _CheckRBTree(_pRoot, count, num);
}
bool CheckColour(Node* pRoot)
{//检查颜色
if (pRoot)
return true;
Node* parent = pRoot->_pParent;
if (pRoot->_color == RED && parent->_color == RED)
{
cout<<"有两个连续的红色节点数,不满足性质3"<<endl;
return false;
}
return CheckColour(pRoot->_pLeft) && CheckColour(pRoot->_pRight);
}
protected:
void _RotateL(Node* parent)
{
Node* pSubR = parent->_pRight;
Node* pSubRL = pSubR->_pLeft;
parent->_pRight = pSubRL;
if(pSubRL)
pSubRL->_pParent = parent;
pSubR->_pLeft = parent;
Node* pparent = parent->_pParent;
parent->_pParent = pSubR;
pSubR->_pParent = pparent;
if(pparent == NULL)
_pRoot = pSubR;
else
{
if(parent == pparent->_pLeft)
pparent->_pLeft = pSubR;
else
pparent->_pRight = pSubR;
}
}
void _RotateR(Node* parent)
{
Node* pSubL = parent->_pLeft;
Node* pSubLR = pSubL->_pRight;
parent->_pLeft = pSubLR;
if(pSubLR)
pSubLR->_pParent = parent;
pSubL->_pRight = parent;
Node* pparent = parent->_pParent;
parent->_pParent = pSubL;
pSubL->_pParent = pparent;
if(pparent == NULL)
_pRoot = pSubL;
else
{
if(parent == pparent->_pLeft)
pparent->_pLeft = pSubL;
else
pparent->_pRight = pSubL;
}
}
void _InOrder(Node* pRoot)
{
if(pRoot)
{
_InOrder(pRoot->_pLeft);
cout<<pRoot->_key<<" ";
_InOrder(pRoot->_pRight);
}
}
bool _CheckRBTree(Node* pRoot, const size_t blackCount, size_t k)
{
//检查黑色结点数目
if (pRoot == NULL)
return true;
if (pRoot->_color == BLACK)
++k;
if (pRoot->_pLeft == NULL && pRoot->_pRight == NULL && blackCount != k)
{
cout<<"每条路径上的黑色节点数不相等,不满足性质4"<<endl;
return false;
}
return _CheckRBTree(pRoot->_pLeft, blackCount, k) && _CheckRBTree(pRoot->_pRight, blackCount, k);
}
protected:
Node* _pRoot;
};
void TestRBTree()
{
int a[] = {10, 7, 8, 15, 5, 6, 11, 13, 12};
RBTree<int, int> t;
for(int idx = 0; idx < sizeof(a)/sizeof(a[0]); ++idx)
t.Insert(a[idx], idx);
t.InOrder();
t.CheckRBTree();
}
int main()
{
TestRBTree();
system("pause");
return 0;
}