对平衡的要求低

二叉搜索树

性质:

1.每个节点不是红的就是黑的

2.根节点是黑的

3.若一个节点是红的,则它的两个子节点是黑的(即不能出现两个连续的红的)

4.每条路径的黑节点的数量相等

5.每个叶子节点都是黑的(叶子节点:NIL节点,空节点

最长路径不超过最短路径的两倍

RBTree红黑树_数据RBTree红黑树_结构_02

调整情况

cur是刚插入的节点

1.叔叔存在,且为红

RBTree红黑树_数据_03

根是红色的,可能会不满足RBTree树的规则(eg:出现连续的两个红色),所以还需要继续向上调整

2.叔叔不存在或者叔叔存在且为黑

RBTree红黑树_数据_04

然后接着第三种情况

3.

RBTree红黑树_数据_05

RBTree红黑树_结构_06

根是黑色的,不用再继续向上调整了

左旋

RBTree红黑树_数据_07

右旋

RBTree红黑树_结构_08

代码:

#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;
}

结果:

RBTree红黑树_结构_09

RBTree红黑树_结构_10