对平衡的要求低
二叉搜索树
性质:
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; }
结果: