對平衡的要求低
二叉搜索樹
性質:
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; }
結果: