对平衡的要求低
二叉搜索树
性质:
1.每个节点不是红的就是黑的
2.根节点是黑的
3.若一个节点是红的,则它的两个子节点是黑的(即不能出现两个连续的红的)
4.每条路径的黑节点的数量相等
5.每个叶子节点都是黑的(叶子节点:NIL节点,空节点)
最长路径不超过最短路径的两倍
调整情况
cur是刚插入的节点
1.叔叔存在,且为红
根是红色的,可能会不满足RBTree树的规则(eg:出现连续的两个红色),所以还需要继续向上调整
2.叔叔不存在或者叔叔存在且为黑
然后接着第三种情况
3.
根是黑色的,不用再继续向上调整了
左旋
右旋
代码:
#include <iostream>
using namespace std;
enum color
{
RED,
BLACK
};
template<class K,class V>
struct RBTreeNode
{
K _key;
V _value;
RBTreeNode<K ,V>* _parent;
RBTreeNode<K ,V>* _left;
RBTreeNode<K ,V>* _right;
color _col;
RBTreeNode( const K & key,const V& value) //构造函数
:_key( key)
,_value( value)
,_parent( NULL)
,_left( NULL)
,_right( NULL)
,_col( RED) //节点默认颜色:红,因为不会影响插入
{}
};
template<class K,class V>
class RBTree
{
typedef RBTreeNode <K,V> Node;
private:
Node* _root;
public:
RBTree() //构造函数
:_root( NULL)
{}
bool Insert(const K& key,const V& value)
{
if(_root==NULL )
{
_root= new Node (key,value);
}
else
{
Node* cur=_root;
Node* parent=NULL ;
while(cur)
{
parent=cur;
if(cur->_key>key ) //插左
{
cur=cur->_left;
}
else if (cur->_key<key) //插右
{
cur=cur->_right;
}
else
{
return false ;
}
}
cur= new Node (key,value);
if(parent->_key>key ) //插左
{
parent->_left=cur;
}
else //插右
{
parent->_right=cur;
}
cur->_parent=parent;
//调整
while(cur!=_root && parent->_col==RED) //parent为红,则包含着其父为黑
{
Node* grandfather=parent->_parent;
if(grandfather->_left==parent)
{
Node* uncle=grandfather->_right;
if(uncle && uncle->_col==RED) //调整情况1
{
parent->_col= BLACK ;
uncle->_col= BLACK ;
grandfather->_col= RED ;
//因为把根调整成了红色,可能会影响RBTree的规则,所以要继续上调
cur=grandfather;
parent=cur->_parent;
}
else
{
//调整情况2,先变化成情况3
if(cur==parent->_right)
{
RotateL(parent); //左旋
swap(parent,cur);
}
//调整情况3
parent->_col= BLACK ;
grandfather->_col= RED ;
RotateR(grandfather); //右旋
break; //根是黑色的,不用再继续向上调整了
}
}
else //grandfather->_right==parent,内容大体同上
{
Node* uncle=grandfather->_left;
if(uncle && uncle->_col==RED) //调整情况1
{
parent->_col= BLACK ;
uncle->_col= BLACK ;
grandfather->_col= RED ;
//继续上调
cur=grandfather;
parent=cur->_parent;
}
else
{
//调整情况2,先变化成情况3
if(cur==parent->_left)
{
RotateR(parent); //右旋
swap(parent,cur);
}
//调整情况3
parent->_col= BLACK ;
grandfather->_col= RED ;
RotateL(grandfather); //左旋
break; //根是黑色的,不用再继续向上调整了
}
}
} //调整结束
}
_root->_col= BLACK;
return true ;
}
Node* Find(const K& key)
{
Node* cur=_root;
while(cur)
{
if(cur->_key>key )
cur=cur->_left;
else if (cur->_key<key)
cur=cur->_right;
else //cur->_key==key,find it!
return cur;
}
return NULL ;
}
bool Isbalance()
{
if(_root==NULL )
return true ;
if(_root->_col==RED )
return false ;
int k=0; //计算黑节点的个数,作为一个基准值
Node* cur=_root;
while(cur)
{
if(cur->_col==BLACK )
k++;
cur=cur->_left;
}
int count=0;
return _Isbalance(_root,k,count);
}
void InOrder() //中序遍历输出
{
_InOrder(_root);
cout<<endl;
}
protected:
void RotateL(Node * parent)
{
Node* subR=parent ->_right;
Node* subRL=subR->_left;
parent->_right=subRL;
if(subRL)
{
subRL->_parent= parent ;
}
subR->_left= parent;
Node* ppNode=parent ->_parent;
parent->_parent=subR;
if(ppNode==NULL )
{
subR->_parent= NULL ;
_root=subR;
}
else
{
if(ppNode->_left==parent )
ppNode->_left=subR;
else
ppNode->_right=subR;
subR->_parent=ppNode;
}
}
void RotateR(Node * parent)
{
Node* subL=parent ->_left;
Node* subLR=subL->_right;
parent->_left=subLR;
if(subLR)
{
subLR->_parent= parent ;
}
subL->_right= parent;
Node* ppNode=parent ->_parent;
parent->_parent=subL;
if(ppNode==NULL )
{
subL->_parent= NULL ;
_root=subL;
}
else
{
if(ppNode->_left==parent )
ppNode->_left=subL;
else
ppNode->_right=subL;
subL->_parent=ppNode;
}
}
bool _Isbalance(Node * root,const int k,int count)
{
if(root ==NULL)
return false ;
if(root ->_col==RED && root->_parent->_col==RED ) //连续的红节点
{
cout<<"连续输出红节点" <<endl;
return false ;
}
if(root ->_col==BLACK)
count++; //记录出现的黑节点的数
if(root ->_left==NULL && root->_right==NULL && k!=count)
{
cout<<"黑色节点数不等" <<endl;
return false ;
}
return _Isbalance(root ->_left,k,count)+_Isbalance( root->_right,k ,count);
}
void _InOrder(Node * root)
{
if(root ==NULL)
return;
_InOrder( root->_left);
cout<< root->_key<<" " ;
_InOrder( root->_right);
}
};
void test()
{
RBTree<int ,int> rbt;
int a[]={27,20,30,18,25,28,40,23,35,29};
for(int i=0;i<sizeof(a)/ sizeof(a[0]);i++)
{
rbt.Insert(a[i],i);
}
rbt.InOrder();
rbt.Isbalance();
}
int main()
{
test();
system( "pause");
return 0;
}
结果:
本文出自 “追寻内心的声音” 博客,请务必保留此出处http://ljy789.blog.51cto.com/10697684/1829933