1.概念:
红黑树是一颗二叉搜索树,它在每一个节点上增加了一个存储位来表示节点的颜色(红/黑)。红黑树保证最长路径不超过最短路径的2倍,因而近似于平衡。
2.性质:
(1)每一个节点,不是红色就是黑色。
(2)根节点是黑色的。
(3)不能有连续的红节点。
(4)对于每个节点,从该节点到其所有后代叶子节点的路径上,黑节点的数目相等。
(5)每一个NIL(空节点)节点是黑色的。
3.插入的情况
cur为当前节点/p为父节点/pp为祖先/u为叔叔节点
(1)cur为红,p为红,pp为黑,u存在且为红。
思路:将p,u改为黑,pp改为红,然后pp当cur,继续向上调整。
调整前的图
调整后的图
(2)cur为红,p为红,pp为黑,u不存在/为黑.
思路:进行单旋转
进行右单旋:
旋转前的图
旋转后的图
左单旋也是类似的
(3)cur为红,p为红,pp为黑,u不存在/为黑.
思路:进行双旋转
进行左右旋转
旋转前的图
旋转后的图
右左旋转也是类似的。
4.判断平衡:根据它的性质来判定它是否平衡。
5.代码:
#pragma once
enum Colour
{
RED,
BLACK,
};
template<class K,class V>
struct RBTreeNode
{
RBTreeNode<K,V>* _left;
RBTreeNode<K,V>* _right;
RBTreeNode<K,V>* _parent;
K _key;
V _value;
Colour _col;
RBTreeNode(const K& key,const V& value)
:_key(key)
,_value(value)
,_left(NULL)
,_right(NULL)
,_parent(NULL)
,_col(RED)
{}
};
template<class K,class V>
class RBTree
{
typedef RBTreeNode<K,V> Node;
public:
RBTree()
:_root(NULL)
{}
bool Insert(const K& key,const V& value)
{
if(_root==NULL)
{
_root=new Node(key,value);
_root->_col =BLACK;
return true;
}
Node* cur=_root;
Node* parent=cur;
while(cur)
{
if(cur->_key <key)
{
parent=cur;
cur=cur->_right ;
}
else if(cur->_key >key)
{
parent=cur;
cur=cur->_left ;
}
else
return false;
}
cur=new Node(key,value);
if(parent->_key <key)
{
parent->_right =cur;
cur->_parent =parent;
}
else
{
parent->_left =cur;
cur->_parent =parent;
}
//调整RB节点
while(cur!=_root&&parent->_col ==RED) //祖先肯定存在并且为黑
{
Node* ppNode=parent->_parent ;
Node* uncle=NULL;
if(ppNode->_left ==parent)
uncle=ppNode->_right ;
else
uncle=ppNode->_left ;
//第一种情况
if(uncle&&uncle->_col ==RED)
{
uncle->_col =BLACK;
parent->_col =BLACK;
ppNode->_col =RED;
cur=ppNode;
parent=ppNode->_parent ;
}
//第二种情况
else if((uncle==NULL)||(uncle->_col =BLACK))
{
if(ppNode->_left ==parent&&parent->_left ==cur)
{
RotateR(ppNode);
break;
}
else if(ppNode->_right ==parent&&parent->_right ==cur)
{
RotateL(ppNode);
break;
}
//第三种情况
else if(ppNode->_left ==parent&&parent->_right ==cur)
{
RotateLR(ppNode);
break;
}
else if(ppNode->_right ==parent&&parent->_left ==cur)
{
RotateRL(ppNode);
break;
}
}
}
_root->_col =BLACK;
return true;
}
bool IsBlance()
{
if(_root==NULL)
return true;
if(_root->_col ==RED) //根节点必须是黑色
return false;
//统计任意一条路径上黑节点的个数
int count=0;
Node* cur=_root;
while(cur)
{
if(cur->_col ==BLACK)
count++;
cur=cur->_left ;
}
int num=0;
return _IsBlance(_root,num,count);
}
void InOrder()
{
_InOrder(_root);
}
~RBTree()
{
_Destory(_root);
}
protected:
void _Destory(Node* root)
{
if(_root==NULL)
return;
_Destory(root->_left );
_Destory(root->_right );
delete root;
}
bool _IsBlance(Node* root,int num,const int& count)
{
if(root==NULL) //访问到叶子节点了
return num==count;
if(root->_col ==RED&&root->_parent ->_col ==RED) //不能有相连的红节点
return false;
if(root->_col ==BLACK)
num++;
return _IsBlance(root->_left ,num,count)&&_IsBlance(root->_right ,num,count);
}
void _InOrder(Node* root)
{
if(root==NULL)
return;
_InOrder(root->_left );
cout<<root->_key <<" "<<root->_col <<endl;
_InOrder(root->_right );
}
void RotateLR(Node* ppNode)
{
RotateL(ppNode->_left );
RotateR(ppNode);
}
void RotateRL(Node* ppNode)
{
RotateR(ppNode->_right );
RotateL(ppNode);
}
void RotateR(Node* ppNode)
{
Node* parent=ppNode->_left ;
Node* subR=parent->_right ;
ppNode->_left =subR;
if(subR)
subR->_parent =ppNode;
Node* pppNode=ppNode->_parent ;
if(pppNode==NULL)
{
_root=parent;
parent->_parent =NULL;
}
else
{
if(pppNode->_left ==ppNode)
pppNode->_left =parent;
else
pppNode->_right =parent;
parent->_parent =pppNode;
}
parent->_right =ppNode;
ppNode->_parent =parent;
parent->_col =BLACK;
ppNode->_col =RED;
}
void RotateL(Node* ppNode)
{
Node* parent=ppNode->_right ;
Node* subL=parent->_left ;
ppNode->_right =subL;
if(subL)
subL->_parent =ppNode;
Node* pppNode=ppNode->_parent ;
if(pppNode==NULL)
{
_root=parent;
parent->_parent =NULL;
}
else
{
if(pppNode->_left ==ppNode)
pppNode->_left =parent;
else
pppNode->_right =parent;
parent->_parent =pppNode;
}
parent->_left =ppNode;
ppNode->_parent =parent;
parent->_col =BLACK;
ppNode->_col =RED;
}
private:
Node* _root;
};
void TestRBTree()
{
RBTree<int,int> t;
//int a[]={4,3,8,2,10,9};
int a[]={16,3,7,9,11,26,18,14};
//int a[]={16,3,7,9,11,26,18};
for(int i=0;i<sizeof(a)/sizeof(a[0]);++i)
{
t.Insert (a[i],i);
}
t.InOrder (); //红 0 黑 1
cout<<t.IsBlance ()<<endl;
}