紅黑樹,作為一種廣泛使用的數(shù)據(jù)結(jié)構(gòu),我想大家應(yīng)該都不會陌生。
談到紅黑樹的用途,最廣為人知的應(yīng)該就是紅黑樹在C++ STL中的應(yīng)用了,在set, multiset, map, multimap等中,都應(yīng)用了紅黑樹。但是,rb_tree本身并不開放給外界使用。
?
今天,我將介紹,STL源碼中,紅黑樹的具體實(shí)現(xiàn)(因?yàn)槠?#xff0c;這里不包括刪除操作)。
因?yàn)槲恼碌闹饕康氖欠治鯯TL中的源碼,所以對于紅黑樹的具體實(shí)現(xiàn)并不展開,這類文章,大家可以到網(wǎng)上查找。這里推薦wiki上的一篇。?
首先,我還是簡要的介紹一下紅黑樹的構(gòu)造、維護(hù)思想。
?
紅黑樹:
紅黑樹是二叉查找樹(BST),同時也是一種平衡二叉查找樹。
雖然它的平衡不如AVL樹,但是,它和AVL樹一樣都對插入時間、刪除時間和查找時間提供了最好可能的最壞情況擔(dān)保。???????
它可以在O(logn)時間內(nèi)做查找,插入和刪除,這里的n是樹中元素的數(shù)目。
?
紅黑樹性質(zhì): 紅黑樹是每個節(jié)點(diǎn)都帶有顏色屬性的二叉查找樹,顏色為紅色或黑色。在二叉查找樹強(qiáng)制一般要求以外,對于任何有效的紅黑樹我們增加了如下的額外要求:?
性質(zhì)1. 節(jié)點(diǎn)是紅色或黑色。? 性質(zhì)2. 根是黑色。? 性質(zhì)3. 所有葉子都是黑色(葉子是NIL節(jié)點(diǎn))。? 性質(zhì)4. 每個紅色節(jié)點(diǎn)的兩個子節(jié)點(diǎn)都是黑色。(從每個葉子到根的所有路徑上不能有兩個連續(xù)的紅色節(jié)點(diǎn))? 性質(zhì)5. 從任一節(jié)點(diǎn)到其每個葉子的所有簡單路徑都包含相同數(shù)目的黑色節(jié)點(diǎn)。?
這些約束強(qiáng)制了紅黑樹的關(guān)鍵性質(zhì):?從根到葉子的最長的可能路徑不多于最短的可能路徑的兩倍長。結(jié)果是這個樹大致上是平衡的。 因?yàn)楦鶕?jù)屬性5所有最長的路徑都有相同數(shù)目的黑色節(jié)點(diǎn),這就表明了沒有路徑能多于任何其他路徑的兩倍長。?
?
紅黑樹操作: 恢復(fù)紅黑樹的屬性需要少量(O(log n))的顏色變更(實(shí)際是非??焖俚?和不超過三次樹旋轉(zhuǎn)(對于插入操作是兩次)。 雖然插入和刪除很復(fù)雜,但操作時間仍可以保持為?O(log n)?次。?
插入節(jié)點(diǎn):
在討論紅黑樹的插入操作之前必須要明白,任何一個即將插入的新結(jié)點(diǎn)的初始顏色都為紅色。這一點(diǎn)很容易理解,因?yàn)椴迦牒邳c(diǎn)會增加某條路徑上黑結(jié)點(diǎn)的數(shù)目,從而導(dǎo)致整棵樹黑高度的不平衡。 但如果新結(jié)點(diǎn)父結(jié)點(diǎn)為紅色時(如圖2所示),將會違返紅黑樹性質(zhì):一條路徑上不能出現(xiàn)相鄰的兩個紅色結(jié)點(diǎn)。這時就需要通過一系列操作來使紅黑樹保持平衡。
刪除節(jié)點(diǎn): 1、刪除操作中真正被刪除的必定是只有一個紅色孩子或沒有孩子的結(jié)點(diǎn)。
2、如果真正的刪除點(diǎn)是一個紅色結(jié)點(diǎn),那么它必定是一個葉子結(jié)點(diǎn)。
?
?
STL源碼實(shí)現(xiàn):
?
一、下面代碼定義了紅黑樹的節(jié)點(diǎn)信息:
?
[cpp]?view plaincopy
typedef?bool?__rb_tree_color_type;???????????????? const?__rb_tree_color_type?__rb_tree_red?=?false;????????? const?__rb_tree_color_type?__rb_tree_black?=?true;???????? ?? struct?__rb_tree_node_base?? {?? ????typedef?__rb_tree_color_type?color_type;?? ????typedef?__rb_tree_node_base*?base_ptr;?? ?????? ????color_type?color;????? ????base_ptr?parent;?????? ????base_ptr?left;???????? ????base_ptr?right;??????? ?????? ????static?base_ptr?minimum(base_ptr?x)?? ????{?? ????????while?(x->left?!=?0)?x?=?x->left;??? ????????return?x;????????????????????????????? ????}?? ?????? ????static?base_ptr?maximum(base_ptr?x)?? ????{?? ????????while?(x->right?!=?0)?x?=?x->right;????? ????????return?x;????????????????????????????? ????}?? };?? ?? template?<class?Value>?? struct?__rb_tree_node?:?public?__rb_tree_node_base?? {?? ????typedef?__rb_tree_node<Value>*?link_type;?? ????Value?value_field;???? };??
由上面的定義可以看出來,每個結(jié)點(diǎn)維護(hù)了三個指針和兩個信息:父結(jié)點(diǎn)parent,左子結(jié)點(diǎn)left,右子結(jié)點(diǎn)right,同時還有一個顏色標(biāo)記color,再就是結(jié)點(diǎn)的值value_field。同時可以求得當(dāng)以某個結(jié)點(diǎn)為根的最小與最大結(jié)點(diǎn)。
?
二、紅黑樹的迭代器定義:
?
迭代器是STL里面非常重要的一部分,這里就不細(xì)說了。我們直接來看看__rb_tree_iterator提供了哪些功能。因?yàn)?strong>,__rb_tree_iterator繼承自__rb_tree_base_iterator,
所以我們先來看__rb_tree_base_iterator這個結(jié)構(gòu)。
[cpp]?view plaincopy
truct?__rb_tree_base_iterator?? {?? ????typedef?__rb_tree_node_base::base_ptr?base_ptr;?? ????typedef?bidirectional_iterator_tag?iterator_category;?? ????typedef?ptrdiff_t?difference_type;?? ?????? ????base_ptr?node;???? ?????? ?????? ????void?increment()?? ????{?? ????????if?(node->right?!=?0)?{???????? ????????????node?=?node->right;???????? ????????????while?(node->left?!=?0)???? ????????????????node?=?node->left;????????? ????????}?? ????????else?{???????????????????? ????????????base_ptr?y?=?node->parent;????? ????????????while?(node?==?y->right)?{????? ????????????????node?=?y;????????????????? ????????????????y?=?y->parent;?? ????????????}?? ????????????if?(node->right?!=?y)?????????? ????????????????node?=?y;????????????????? ?????????????? ????????}????????????????????????? ?????????? ?????????? ?????????? ?????????? ????}?? ?????? ?????? ????void?decrement()?? ????{?? ????????if?(node->color?==?__rb_tree_red?&&???? ????????????node->parent->parent?==?node)??????? ????????????node?=?node->right;???????????????? ?????????? ?????????? ????????else?if?(node->left?!=?0)?{???????????? ????????????base_ptr?y?=?node->left;??????????? ????????????while?(y->right?!=?0)?????????????????? ????????????????y?=?y->right;?????????????????????? ????????????node?=?y;????????????????????????? ????????}?? ????????else?{???????????????????????????? ????????????base_ptr?y?=?node->parent;????????????? ????????????while?(node?==?y->left)?{?????????????? ????????????????node?=?y;????????????????????????? ????????????????y?=?y->parent;????????????????????? ????????????}?? ????????????node?=?y;????????????????????????? ????????}?? ????}?? };??
?
可以看到__rb_tree_base_iterator里面只有兩個函數(shù):increment()和decrement()。
這兩個函數(shù)也是很好理解:
increment():找到比當(dāng)前節(jié)點(diǎn)大的最小的那個節(jié)點(diǎn)。用于__rb_tree_iterator中重載++操作符的調(diào)用。
decrement():找到比當(dāng)前節(jié)點(diǎn)小的最大的那個節(jié)點(diǎn)。用于__rb_tree_iterator中重載--操作符的調(diào)用。
?
再來看看__rb_tree_iterator提供了哪些功能:
[cpp]?view plaincopy
template?<class?Value,?class?Ref,?class?Ptr>?? struct?__rb_tree_iterator?:?public?__rb_tree_base_iterator?? {?? ????typedef?Value?value_type;?? ????typedef?Ref?reference;?? ????typedef?Ptr?pointer;?? ????typedef?__rb_tree_iterator<Value,?Value&,?Value*>?????iterator;?? ????typedef?__rb_tree_iterator<Value,?const?Value&,?const?Value*>?const_iterator;?? ????typedef?__rb_tree_iterator<Value,?Ref,?Ptr>???self;?? ????typedef?__rb_tree_node<Value>*?link_type;?? ?????? ????__rb_tree_iterator()?{}?? ????__rb_tree_iterator(link_type?x)?{?node?=?x;?}?? ????__rb_tree_iterator(const?iterator&?it)?{?node?=?it.node;?}?? ?????? ????reference?operator*()?const?{?return?link_type(node)->value_field;?}?? #ifndef?__SGI_STL_NO_ARROW_OPERATOR?? ????pointer?operator->()?const?{?return?&(operator*());?}?? #endif?/*?__SGI_STL_NO_ARROW_OPERATOR?*/?? ?????? ????self&?operator++()?{?increment();?return?*this;?}????? ????self?operator++(int)?{?? ????????self?tmp?=?*this;?? ????????increment();?? ????????return?tmp;?? ????}?? ?????? ????self&?operator--()?{?decrement();?return?*this;?}????? ????self?operator--(int)?{?? ????????self?tmp?=?*this;?? ????????decrement();?? ????????return?tmp;?? ????}?? };?? ?? inline?bool?operator==(const?__rb_tree_base_iterator&?x,?? ???????????????????????const?__rb_tree_base_iterator&?y)?{?? ????return?x.node?==?y.node;?? ?????? }?? ?? inline?bool?operator!=(const?__rb_tree_base_iterator&?x,?? ???????????????????????const?__rb_tree_base_iterator&?y)?{?? ????return?x.node?!=?y.node;?? ?????? }??
?
上述代碼等價于下面代碼,結(jié)構(gòu)功能一目了然:
[cpp]?view plaincopy
struct?__rb_tree_iterator?? {?? ????typedef?__rb_tree_node<T>*?link_type;??? ?? ????operator*();?? ????operator->();?????? ????operator++();????? ????operator++(int);?? ????operator--();????? ????operator--(int);?? }??
?
三、RB_tree的數(shù)據(jù)結(jié)構(gòu):
?
下面是rb_tree的定義,你可以看到里面有專屬的空間配置器,因?yàn)榧t黑樹是動態(tài)增長的,所以每次增加或刪除結(jié)點(diǎn)時都要進(jìn)行配置,它有一個專用的空間配置器,用來每次申請一個結(jié)點(diǎn)的內(nèi)存或歸還一個結(jié)點(diǎn)的內(nèi)存。還有各種類別定義,用來維護(hù)整棵RB_tree的三筆數(shù)據(jù)(其中有個仿函數(shù),functor,用來變現(xiàn)節(jié)點(diǎn)的大小比較方式),以及一些member functions的定義或聲明。
?
1、專屬的空間配置器rb_tree_node_allocator,每次配置一個節(jié)點(diǎn),它使用的是simple_alloc<>。
[cpp]?view plaincopy
template?<class?Key,?class?Value,?class?KeyOfValue,?class?Compare,?? ??????????class?Alloc?=?alloc>?? class?rb_tree?{?? protected:?? ??typedef?void*?void_pointer;?? ??typedef?__rb_tree_node_base*?base_ptr;?? ??typedef?__rb_tree_node<Value>?rb_tree_node;?? ??typedef?simple_alloc<rb_tree_node,?Alloc>?rb_tree_node_allocator;?? ??typedef?__rb_tree_color_type?color_type;?? ...?? };??
2、一些與節(jié)點(diǎn)相關(guān)的函數(shù):如get_node(),put_node(),create_node(),clone_node(),destroy_node()。
[cpp]?view plaincopy
public:?? ???? ??typedef?Key?key_type;?? ??typedef?Value?value_type;?? ??typedef?value_type*?pointer;?? ??typedef?const?value_type*?const_pointer;?? ??typedef?value_type&?reference;?? ??typedef?const?value_type&?const_reference;?? ??typedef?rb_tree_node*?link_type;?? ??typedef?size_t?size_type;?? ??typedef?ptrdiff_t?difference_type;?? protected:?? ??link_type?<strong>get_node</strong>()?{?return?rb_tree_node_allocator::allocate();?}?? ??void?put_node(link_type?p)?{?rb_tree_node_allocator::deallocate(p);?}?? ?? ??link_type?<strong>create_node</strong>(const?value_type&?x)?{?? ????link_type?tmp?=?get_node();??????????? ????__STL_TRY?{?? ??????construct(&tmp->value_field,?x);????? ????}?? ????__STL_UNWIND(put_node(tmp));?? ????return?tmp;?? ??}?? ?? ??link_type?<strong>clone_node</strong>(link_type?x)?{???? ????link_type?tmp?=?create_node(x->value_field);?? ????tmp->color?=?x->color;?? ????tmp->left?=?0;?? ????tmp->right?=?0;?? ????return?tmp;?? ??}?? ?? ??void?<strong>destroy_node</strong>(link_type?p)?{?? ????destroy(&p->value_field);?????????? ????put_node(p);?????????????????????? ??}??
3、rb_tree的構(gòu)造函數(shù)
1、以現(xiàn)有的RB_tree復(fù)制一個新的RB_tree
2、創(chuàng)造一個空的RB_tree
?
[cpp]?view plaincopy
void?init()?{?? ????header?=?get_node();?????? ????color(header)?=?__rb_tree_red;??? ????????????????????????????????????? ????root()?=?0;?? ????leftmost()?=?header;?????? ????rightmost()?=?header;????? ??}?? public:?? ?????????????????????????????????? ??rb_tree(const?Compare&?comp?=?Compare())?? ????:?node_count(0),?key_compare(comp)?{?init();?}?? ?? ???? ??rb_tree(const?rb_tree<Key,?Value,?KeyOfValue,?Compare,?Alloc>&?x)??? ????:?node_count(0),?key_compare(x.key_compare)?? ??{??? ????header?=?get_node();?????? ????color(header)?=?__rb_tree_red;???? ????if?(x.root()?==?0)?{?????? ??????root()?=?0;?? ??????leftmost()?=?header;???? ??????rightmost()?=?header;??? ????}?? ????else?{???? ??????__STL_TRY?{?? ????????root()?=?__copy(x.root(),?header);???????? ??????}?? ??????__STL_UNWIND(put_node(header));?? ??????leftmost()?=?minimum(root());??? ??????rightmost()?=?maximum(root());?????? ????}?? ????node_count?=?x.node_count;?? ??}?? ??~rb_tree()?{?? ????clear();?? ????put_node(header);?? ??}?? ??rb_tree<Key,?Value,?KeyOfValue,?Compare,?Alloc>&??? ??operator=(const?rb_tree<Key,?Value,?KeyOfValue,?Compare,?Alloc>&?x);??
?
4、rb_tree的元素操作?
?
1)插入元素的插入操作?insert_equal(),插入的值可以是重復(fù)的。
[cpp]?view plaincopy
?? ?? template?<class?Key,?class?Value,?class?KeyOfValue,?class?Compare,?class?Alloc>?? typename?rb_tree<Key,?Value,?KeyOfValue,?Compare,?Alloc>::iterator?? rb_tree<Key,?Value,?KeyOfValue,?Compare,?Alloc>::<strong>insert_equal</strong>(const?Value&?v)?? {?? ??link_type?y?=?header;?? ??link_type?x?=?root();??? ??while?(x?!=?0)?{???????? ????y?=?x;?? ????x?=?key_compare(KeyOfValue()(v),?key(x))???left(x)?:?right(x);?? ?????? ??}?? ??return?__insert(x,?y,?v);?? }??
?
2)插入元素的插入操作?insert_unique(),插入的值不能重復(fù)的。
[cpp]?view plaincopy
?? ?? ?? template?<class?Key,?class?Value,?class?KeyOfValue,?class?Compare,?class?Alloc>?? pair<typename?rb_tree<Key,?Value,?KeyOfValue,?Compare,?Alloc>::iterator,?bool>?? rb_tree<Key,?Value,?KeyOfValue,?Compare,?Alloc>::<strong>insert_unique</strong>(const?Value&?v)?? {?? ??link_type?y?=?header;?? ??link_type?x?=?root();??? ??bool?comp?=?true;?? ??while?(x?!=?0)?{???????? ????y?=?x;?? ????comp?=?key_compare(KeyOfValue()(v),?key(x));??? ????x?=?comp???left(x)?:?right(x);???? ??}?? ???? ?? ??iterator?j?=?iterator(y);????? ??if?(comp)??? ????if?(j?==?begin())????? ??????return?pair<iterator,bool>(__insert(x,?y,?v),?true);?? ???????? ????else?????? ??????--j;???? ??if?(key_compare(key(j.node),?KeyOfValue()(v)))?????? ?????? ????return?pair<iterator,bool>(__insert(x,?y,?v),?true);?? ?? ???? ??return?pair<iterator,bool>(j,?false);?? }??
?
3)真正的插入操作執(zhí)行程序?__insert()
[cpp]?view plaincopy
template?<class?Key,?class?Value,?class?KeyOfValue,?class?Compare,?class?Alloc>?? typename?rb_tree<Key,?Value,?KeyOfValue,?Compare,?Alloc>::iterator?? rb_tree<Key,?Value,?KeyOfValue,?Compare,?Alloc>::?? __insert(base_ptr?x_,?base_ptr?y_,?const?Value&?v)?{?? ?? ??link_type?x?=?(link_type)?x_;?? ??link_type?y?=?(link_type)?y_;?? ??link_type?z;?? ?? ???? ??if?(y?==?header?||?x?!=?0?||?key_compare(KeyOfValue()(v),?key(y)))?{?? ????z?=?create_node(v);???? ????left(y)?=?z;???????????? ????if?(y?==?header)?{?? ??????root()?=?z;?? ??????rightmost()?=?z;?? ????}?? ????else?if?(y?==?leftmost())????? ??????leftmost()?=?z;????????????????? ??}?? ??else?{?? ????z?=?create_node(v);??????? ????right(y)?=?z;????????????????? ????if?(y?==?rightmost())?? ??????rightmost()?=?z;???????????????? ??}?? ??parent(z)?=?y;?????????? ??left(z)?=?0;???????? ??right(z)?=?0;??????????? ???????????????????????????? ??__rb_tree_rebalance(z,?header->parent);?????? ??++node_count;??????? ??return?iterator(z);????? }??
?
4)調(diào)整RB_tree?(旋轉(zhuǎn)及改變顏色)
?
任何插入操作,于節(jié)點(diǎn)插入完畢后,都要做一次調(diào)整操作,將樹的狀態(tài)調(diào)整到符合RB_tree的要求。
__rb_tree_rebalance()是具備如此能力的一個全局函數(shù):
[cpp]?view plaincopy
inline?void??? __rb_tree_rebalance(__rb_tree_node_base*?x,?__rb_tree_node_base*&?root)?? {?? ??x->color?=?__rb_tree_red;???????? ??while?(x?!=?root?&&?x->parent->color?==?__rb_tree_red)?{??? ????if?(x->parent?==?x->parent->parent->left)?{??? ??????__rb_tree_node_base*?y?=?x->parent->parent->right;????? ??????if?(y?&&?y->color?==?__rb_tree_red)?{???????? ????????x->parent->color?=?__rb_tree_black;????????? ????????y->color?=?__rb_tree_black;???????????????? ????????x->parent->parent->color?=?__rb_tree_red;???? ????????x?=?x->parent->parent;?? ??????}?? ??????else?{?????? ????????if?(x?==?x->parent->right)?{??? ??????????x?=?x->parent;?? ??????????__rb_tree_rotate_left(x,?root);??? ????????}?? ????????x->parent->color?=?__rb_tree_black;????? ????????x->parent->parent->color?=?__rb_tree_red;?? ????????__rb_tree_rotate_right(x->parent->parent,?root);??? ??????}?? ????}?? ????else?{???? ??????__rb_tree_node_base*?y?=?x->parent->parent->left;??? ??????if?(y?&&?y->color?==?__rb_tree_red)?{???????? ????????x->parent->color?=?__rb_tree_black;????????? ????????y->color?=?__rb_tree_black;???????????????? ????????x->parent->parent->color?=?__rb_tree_red;???? ????????x?=?x->parent->parent;?????? ??????}?? ??????else?{?????? ????????if?(x?==?x->parent->left)?{????? ??????????x?=?x->parent;?? ??????????__rb_tree_rotate_right(x,?root);???? ????????}?? ????????x->parent->color?=?__rb_tree_black;????? ????????x->parent->parent->color?=?__rb_tree_red;?? ????????__rb_tree_rotate_left(x->parent->parent,?root);??? ??????}?? ????}?? ??}??? ??root->color?=?__rb_tree_black;??? }??
?
上述的調(diào)整函數(shù)需要左旋和右旋:
__rb_tree_rotate_left():左旋
[cpp]?view plaincopy
?? ?? ?? ?? ?? inline?void??? __rb_tree_rotate_left(__rb_tree_node_base*?x,?__rb_tree_node_base*&?root)?? {?? ???? ??__rb_tree_node_base*?y?=?x->right;??? ??x->right?=?y->left;?? ??if?(y->left?!=0)?? ????y->left->parent?=?x;???????? ??y->parent?=?x->parent;?? ?? ???? ??if?(x?==?root)?????????????????????? ????root?=?y;?? ??else?if?(x?==?x->parent->left)???? ????x->parent->left?=?y;?? ??else???????????????????????????? ????x->parent->right?=?y;??????????? ??y->left?=?x;?? ??x->parent?=?y;?? }??
__rb_tree_rotate_right():右旋
[cpp]?view plaincopy
?? ?? inline?void??? __rb_tree_rotate_right(__rb_tree_node_base*?x,?__rb_tree_node_base*&?root)?? {?? ???? ??__rb_tree_node_base*?y?=?x->left;???? ??x->left?=?y->right;?? ??if?(y->right?!=?0)?? ????y->right->parent?=?x;??????? ??y->parent?=?x->parent;?? ?? ???? ??if?(x?==?root)?????????????????????? ????root?=?y;?? ??else?if?(x?==?x->parent->right)??? ????x->parent->right?=?y;?? ??else???????????????????????????? ????x->parent->left?=?y;?? ??y->right?=?x;?? ??x->parent?=?y;?? }??
from:?http://blog.csdn.net/cyh_24/article/details/8068735
總結(jié)
以上是生活随笔為你收集整理的STL的红与黑--rb_tree红黑树的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。