RBTree紅黑樹

對平衡的要求低

二叉搜索樹

性質:

1.每個節點不是紅的就是黑的

2.根節點是黑的

3.若一個節點是紅的,則它的兩個子節點是黑的(即不能出現兩個連續的紅的)

4.每條路徑的黑節點的數量相等

5.每個葉子節點都是黑的(葉子節點:NIL節點,空節點

最長路徑不超過最短路徑的兩倍

wKiom1eWPvOSZSC3AAAN3M2VS5M422.pngwKioL1eWPwqQ3d34AAAnud6Ifns792.png

調整情況

cur是剛插入的節點

1.叔叔存在,且爲紅

wKiom1eWPyrg-MQZAAA85U_X02g842.png

根是紅色的,可能會不滿足RBTree樹的規則(eg:出現連續的兩個紅色),所以還需要繼續向上調整

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

wKioL1eWP0yimf0OAAAyM8q1K4Q517.png

然後接着第三種情況

3.

wKioL1eWP23QjmmhAAAw0Cpy0BA323.png

wKiom1eWP4nxqwV-AAAjLWK6dNw400.png

根是黑色的,不用再繼續向上調整了

左旋

wKioL1eWP6bRmEcpAAAswjbowQk458.png

右旋

wKiom1eWP8GgUyQWAAA4hAfOlT4956.png

代碼:

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

結果:

wKioL1eWQAajxv3vAAAJN38wTBQ030.png

wKiom1eWQBrDBj2vAAAqK8YDVQQ646.png



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章