深度探索紅黑樹

     RB-tree是除AVl-tree之外被廣泛應用的平衡二叉搜素樹,AVL-tree是最早的平衡二叉樹之一,在實際中應用的比較少,windows對進程地址空間的管理用到了AVL樹,紅黑樹廣泛應用在STL中,map和set都是用紅黑樹實現的。
     AVL-tree是一種高度平衡的二叉搜素樹,造成的結果是維護這種高度平衡所付出的代價比從中獲得效率收益還高,所以在實際中應用不多,更多的是用追求局部而不是嚴格整體平衡的紅黑樹。本文將結合stl中rb_tree源碼分析紅黑樹的一些結構。
     RB-tree必須滿足的規則:
        1.每個節點不是紅色就是黑色
        2.根節點爲黑色
        3.如果節點爲紅,其子節點必須爲黑

        4.任一節點到葉節點的任何路徑,所含黑節點的樹必須相同。

  

//rb_tree的定義
/*模板參數的含義:
1.key 表示節點的鍵
2.Value表示節點(key+value)
3.KeyOfValue表示怎麼從key中取出value
4.Compare表示key的比較規則,應爲要排序
5.Alloc分配器
*/
template <class key,class Value,class KeyOfValue,class Compare,class Alloc=alloc>
class rb_tree{
protected:
	size_type node_count;  //記錄數的節點數量,佔4個字節大小
	link_type header;   //頭節點,指向root節點,類似於鏈表的頭節點,它是一個指針,佔4個字節
	Compare key_compare; //節點的key比較規則,實際key_compare是一個函數,函數不佔大小的,但實際上編譯器在處理的時候會添加1個字節
	//根據這裏的分析,rb_tree佔用的大小爲9個字節,考慮對齊規則,rb_tree佔用的大小爲12字節,可以用sizeof(rb_tree)測試驗證
protected:
	typedef __rb_tree_node<Value> rb_tree_node;
	...
public:
	typedef rb_tree_node* link_type;
	...
protected:
	//獲取節header的成員
	link_type& root() const{
		return (link_type&)header->parent;
	}
	link_type& leftmost() const{
		return (link_type&)header->left;
	}
	link_type& rightmost() const{
		return (link_type&)header->right;
	}
	//獲取節點x的成員
	static link_type& left(link_type x){
		return (link_type&)x->left;
	}
	static link_type& right(link_type x){
		return (link_type&)x->right;
	}
	static link_type& parent(link_type x){
		return (link_type&)x->parent;
	}
	static reference value(link_type x){
		return x->value_field;
	}
	static const Key& key(link_type x){
		return KeyOfValue()(value(x));
	}
	static color_type& color(link_type x){
		return (color_type&)(x->color);
	}
	...
public:
	Compare key_comp() const{
		return key_compare;
	}
	iterator begin(){
		return leftmost();
	}
	iterator end(){
		return header;
	}
	bool empty() const{
		return node_count == 0;
	}
	size_type size() const{
		return node_count;
	}
	size_type max_size() const{
		return size_type(-1);
	}
public:
	//將x插入到RB-tree中,保持節點值獨一無二
	pair<iterator, bool> insert_unique(const value_type& x);
	//將x插入到RB-tree中,允許節點值重複
	iterator insert_equal(const value_type& x);
	...
};

   一般來說,我們不應使用rb_tree的iterators改變元素值,因爲元素有其排列規則,雖然源代碼阻止此事,因爲rb_tree將爲
set和map提供底層支持,而map運行元素的data被改變,只有key是不可以改變的
   rb_tree提供兩個insertion操作:insert_unique()和iinsert_equal()前者表示節點的key一定在整個tree中獨一無二,否則出入失敗,後者表示節點的key可重複
        
//測試rb_tree
rb_tree<int, int, identity<int>, less<int>> itree;
cout << itree.empty() << endl; //1
cout << itree.size() << endl;//0

itree.insert_unique(3);
itree.insert_unique(8);
itree.insert_unique(5);
itree.insert_unique(9);
itree.insert_unique(13);
itree.insert_unique(5); //不會被插入
cout << itree.empty() << endl; //0
cout << itree.size() << endl;  //5
cout << itree.count(5) << endl; //1


itree.insert_equal(5);
itree.insert_equal(5);
count << itree.size() << endl; //7
count << itree.count(5) << endl;//3


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