日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

STL的红与黑--rb_tree红黑树

發(fā)布時間:2025/3/21 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 STL的红与黑--rb_tree红黑树 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

紅黑樹,作為一種廣泛使用的數(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;??????????????//?節(jié)點(diǎn)顏色??
  • const?__rb_tree_color_type?__rb_tree_red?=?false;???????//?紅色為?0??
  • const?__rb_tree_color_type?__rb_tree_black?=?true;??????//?黑色為?1??
  • ??
  • struct?__rb_tree_node_base??
  • {??
  • ????typedef?__rb_tree_color_type?color_type;??
  • ????typedef?__rb_tree_node_base*?base_ptr;??
  • ??????
  • ????color_type?color;???//?節(jié)點(diǎn)顏色,非紅即黑。??
  • ????base_ptr?parent;????//?RB?樹的許多操作,必須知道父節(jié)點(diǎn)。??
  • ????base_ptr?left;??????//?指向左節(jié)點(diǎn)。??
  • ????base_ptr?right;?????//?指向右節(jié)點(diǎn)。??
  • ??????
  • ????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)實(shí)值??
  • };??

  • 由上面的定義可以看出來,每個結(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;??//?它用來與容器之間產(chǎn)生一個連結(jié)關(guān)系(make?a?reference)??
  • ??????
  • ????//?以下其實(shí)可實(shí)作於?operator++?內(nèi),因?yàn)樵贌o他處會呼叫此函式了。??
  • ????void?increment()??
  • ????{??
  • ????????if?(node->right?!=?0)?{??????//?如果有右子節(jié)點(diǎn)。狀況(1)??
  • ????????????node?=?node->right;??????//?就向右走??
  • ????????????while?(node->left?!=?0)??//?然後一直往左子樹走到底??
  • ????????????????node?=?node->left;???????//?即是解答??
  • ????????}??
  • ????????else?{??????????????????//?沒有右子節(jié)點(diǎn)。狀況(2)??
  • ????????????base_ptr?y?=?node->parent;???//?找出父節(jié)點(diǎn)??
  • ????????????while?(node?==?y->right)?{???//?如果現(xiàn)行節(jié)點(diǎn)本身是個右子節(jié)點(diǎn),??
  • ????????????????node?=?y;???????????????//?就一直上溯,直到「不為右子節(jié)點(diǎn)」止。??
  • ????????????????y?=?y->parent;??
  • ????????????}??
  • ????????????if?(node->right?!=?y)????????//?「若此時的右子節(jié)點(diǎn)不等於此時的父節(jié)點(diǎn)」。??
  • ????????????????node?=?y;???????????????//?狀況(3)?此時的父節(jié)點(diǎn)即為解答。??
  • ????????????//?否則此時的node?為解答。狀況(4)??
  • ????????}?????????????????????????
  • ????????//?注意,以上判斷「若此時的右子節(jié)點(diǎn)不等於此時的父節(jié)點(diǎn)」,是為了應(yīng)付一種??
  • ????????//?特殊情況:我們欲尋找根節(jié)點(diǎn)的下一節(jié)點(diǎn),而恰巧根節(jié)點(diǎn)無右子節(jié)點(diǎn)。??
  • ????????//?當(dāng)然,以上特殊作法必須配合?RB-tree?根節(jié)點(diǎn)與特殊之header?之間的??
  • ????????//?特殊關(guān)係。??
  • ????}??
  • ??????
  • ????//?以下其實(shí)可實(shí)作於?operator--?內(nèi),因?yàn)樵贌o他處會呼叫此函式了。??
  • ????void?decrement()??
  • ????{??
  • ????????if?(node->color?==?__rb_tree_red?&&??//?如果是紅節(jié)點(diǎn),且??
  • ????????????node->parent->parent?==?node)?????//?父節(jié)點(diǎn)的父節(jié)點(diǎn)等於自己,??
  • ????????????node?=?node->right;??????????????//?狀況(1)?右子節(jié)點(diǎn)即為解答。??
  • ????????//?以上情況發(fā)生於node為header時(亦即?node?為?end()?時)。??
  • ????????//?注意,header?之右子節(jié)點(diǎn)即?mostright,指向整棵樹的?max?節(jié)點(diǎn)。??
  • ????????else?if?(node->left?!=?0)?{??????????//?如果有左子節(jié)點(diǎn)。狀況(2)??
  • ????????????base_ptr?y?=?node->left;?????????//?令y指向左子節(jié)點(diǎn)??
  • ????????????while?(y->right?!=?0)????????????????//?當(dāng)y有右子節(jié)點(diǎn)時??
  • ????????????????y?=?y->right;????????????????????//?一直往右子節(jié)點(diǎn)走到底??
  • ????????????node?=?y;???????????????????????//?最後即為答案??
  • ????????}??
  • ????????else?{??????????????????????????//?既非根節(jié)點(diǎn),亦無左子節(jié)點(diǎn)。??
  • ????????????base_ptr?y?=?node->parent;???????????//?狀況(3)?找出父節(jié)點(diǎn)??
  • ????????????while?(node?==?y->left)?{????????????//?當(dāng)現(xiàn)行節(jié)點(diǎn)身為左子節(jié)點(diǎn)??
  • ????????????????node?=?y;???????????????????????//?一直交替往上走,直到現(xiàn)行節(jié)點(diǎn)??
  • ????????????????y?=?y->parent;???????????????????//?不為左子節(jié)點(diǎn)??
  • ????????????}??
  • ????????????node?=?y;???????????????????????//?此時之父節(jié)點(diǎn)即為答案??
  • ????????}??
  • ????}??
  • };??

  • ?

    可以看到__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;??
  • ????//?兩個迭代器相等,意指其所指的節(jié)點(diǎn)相等。??
  • }??
  • ??
  • inline?bool?operator!=(const?__rb_tree_base_iterator&?x,??
  • ???????????????????????const?__rb_tree_base_iterator&?y)?{??
  • ????return?x.node?!=?y.node;??
  • ????//?兩個迭代器不等,意指其所指的節(jié)點(diǎn)不等。??
  • }??
  • ?

    上述代碼等價于下面代碼,結(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:??
  • ??//?注意,沒有定義?iterator(喔,不,定義在後面)??
  • ??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);???//?建構(gòu)內(nèi)容??
  • ????}??
  • ????__STL_UNWIND(put_node(tmp));??
  • ????return?tmp;??
  • ??}??
  • ??
  • ??link_type?<strong>clone_node</strong>(link_type?x)?{??//?複製一個節(jié)點(diǎn)(的值和色)??
  • ????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);????????//?解構(gòu)內(nèi)容??
  • ????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();????//?產(chǎn)生一個節(jié)點(diǎn)空間,令?header?指向它??
  • ????color(header)?=?__rb_tree_red;?//?令?header?為紅色,用來區(qū)分?header????
  • ???????????????????????????????????//?和?root(在?iterator.operator++?中)??
  • ????root()?=?0;??
  • ????leftmost()?=?header;????//?令?header?的左子節(jié)點(diǎn)為自己。??
  • ????rightmost()?=?header;???//?令?header?的右子節(jié)點(diǎn)為自己。??
  • ??}??
  • public:??
  • ????????????????????????????????//?allocation/deallocation??
  • ??rb_tree(const?Compare&?comp?=?Compare())??
  • ????:?node_count(0),?key_compare(comp)?{?init();?}??
  • ??
  • ??//?以另一個?rb_tree?物件?x?為初值??
  • ??rb_tree(const?rb_tree<Key,?Value,?KeyOfValue,?Compare,?Alloc>&?x)???
  • ????:?node_count(0),?key_compare(x.key_compare)??
  • ??{???
  • ????header?=?get_node();????//?產(chǎn)生一個節(jié)點(diǎn)空間,令?header?指向它??
  • ????color(header)?=?__rb_tree_red;??//?令?header?為紅色??
  • ????if?(x.root()?==?0)?{????//??如果?x?是個空白樹??
  • ??????root()?=?0;??
  • ??????leftmost()?=?header;??//?令?header?的左子節(jié)點(diǎn)為自己。??
  • ??????rightmost()?=?header;?//?令?header?的右子節(jié)點(diǎn)為自己。??
  • ????}??
  • ????else?{??//??x?不是一個空白樹??
  • ??????__STL_TRY?{??
  • ????????root()?=?__copy(x.root(),?header);??????//???????
  • ??????}??
  • ??????__STL_UNWIND(put_node(header));??
  • ??????leftmost()?=?minimum(root());?//?令?header?的左子節(jié)點(diǎn)為最小節(jié)點(diǎn)??
  • ??????rightmost()?=?maximum(root());????//?令?header?的右子節(jié)點(diǎn)為最大節(jié)點(diǎn)??
  • ????}??
  • ????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
  • //?安插新值;節(jié)點(diǎn)鍵值允許重複。??
  • //?注意,傳回值是一個?RB-tree?迭代器,指向新增節(jié)點(diǎn)??
  • 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();?//?從根節(jié)點(diǎn)開始??
  • ??while?(x?!=?0)?{??????//?從根節(jié)點(diǎn)開始,往下尋找適當(dāng)?shù)陌膊妩c(diǎn)??
  • ????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
  • //?安插新值;節(jié)點(diǎn)鍵值不允許重複,若重複則安插無效。??
  • //?注意,傳回值是個pair,第一元素是個?RB-tree?迭代器,指向新增節(jié)點(diǎn),??
  • //?第二元素表示安插成功與否。??
  • 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();?//?從根節(jié)點(diǎn)開始??
  • ??bool?comp?=?true;??
  • ??while?(x?!=?0)?{??????//?從根節(jié)點(diǎn)開始,往下尋找適當(dāng)?shù)陌膊妩c(diǎn)??
  • ????y?=?x;??
  • ????comp?=?key_compare(KeyOfValue()(v),?key(x));?//?v?鍵值小於目前節(jié)點(diǎn)之鍵值???
  • ????x?=?comp???left(x)?:?right(x);??//?遇「大」則往左,遇「小於或等於」則往右??
  • ??}??
  • ??//?離開?while?迴圈之後,y?所指即安插點(diǎn)之父節(jié)點(diǎn)(此時的它必為葉節(jié)點(diǎn))??
  • ??
  • ??iterator?j?=?iterator(y);???//?令迭代器j指向安插點(diǎn)之父節(jié)點(diǎn)?y??
  • ??if?(comp)?//?如果離開?while?迴圈時?comp?為真(表示遇「大」,將安插於左側(cè))??
  • ????if?(j?==?begin())???//?如果安插點(diǎn)之父節(jié)點(diǎn)為最左節(jié)點(diǎn)??
  • ??????return?pair<iterator,bool>(__insert(x,?y,?v),?true);??
  • ??????//?以上,x?為安插點(diǎn),y?為安插點(diǎn)之父節(jié)點(diǎn),v?為新值。??
  • ????else????//?否則(安插點(diǎn)之父節(jié)點(diǎn)不為最左節(jié)點(diǎn))??
  • ??????--j;??//?調(diào)整?j,回頭準(zhǔn)備測試...??
  • ??if?(key_compare(key(j.node),?KeyOfValue()(v)))??????
  • ????//?小於新值(表示遇「小」,將安插於右側(cè))??
  • ????return?pair<iterator,bool>(__insert(x,?y,?v),?true);??
  • ??
  • ??//?進(jìn)行至此,表示新值一定與樹中鍵值重複,那麼就不該插入新值。??
  • ??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)?{??
  • //?參數(shù)x_?為新值安插點(diǎn),參數(shù)y_?為安插點(diǎn)之父節(jié)點(diǎn),參數(shù)v?為新值。??
  • ??link_type?x?=?(link_type)?x_;??
  • ??link_type?y?=?(link_type)?y_;??
  • ??link_type?z;??
  • ??
  • ??//?key_compare?是鍵值大小比較準(zhǔn)則。應(yīng)該會是個?function?object。??
  • ??if?(y?==?header?||?x?!=?0?||?key_compare(KeyOfValue()(v),?key(y)))?{??
  • ????z?=?create_node(v);??//?產(chǎn)生一個新節(jié)點(diǎn)??
  • ????left(y)?=?z;??????????//?這使得當(dāng)?y?即為?header時,leftmost()?=?z??
  • ????if?(y?==?header)?{??
  • ??????root()?=?z;??
  • ??????rightmost()?=?z;??
  • ????}??
  • ????else?if?(y?==?leftmost())???//?如果y為最左節(jié)點(diǎn)??
  • ??????leftmost()?=?z;???????????????//?維護(hù)leftmost(),使它永遠(yuǎn)指向最左節(jié)點(diǎn)??
  • ??}??
  • ??else?{??
  • ????z?=?create_node(v);?????//?產(chǎn)生一個新節(jié)點(diǎn)??
  • ????right(y)?=?z;???????????????//?令新節(jié)點(diǎn)成為安插點(diǎn)之父節(jié)點(diǎn)?y?的右子節(jié)點(diǎn)??
  • ????if?(y?==?rightmost())??
  • ??????rightmost()?=?z;??????????????//?維護(hù)rightmost(),使它永遠(yuǎn)指向最右節(jié)點(diǎn)??
  • ??}??
  • ??parent(z)?=?y;????????//?設(shè)定新節(jié)點(diǎn)的父節(jié)點(diǎn)??
  • ??left(z)?=?0;??????//?設(shè)定新節(jié)點(diǎn)的左子節(jié)點(diǎn)??
  • ??right(z)?=?0;?????????//?設(shè)定新節(jié)點(diǎn)的右子節(jié)點(diǎn)??
  • ??????????????????????????//?新節(jié)點(diǎn)的顏色將在?__rb_tree_rebalance()?設(shè)定(並調(diào)整)??
  • ??__rb_tree_rebalance(z,?header->parent);????//?參數(shù)一為新增節(jié)點(diǎn),參數(shù)二為?root??
  • ??++node_count;?????//?節(jié)點(diǎn)數(shù)累加??
  • ??return?iterator(z);???//?傳回一個迭代器,指向新增節(jié)點(diǎn)??
  • }??

  • ?

    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;??????//?新節(jié)點(diǎn)必為紅??
  • ??while?(x?!=?root?&&?x->parent->color?==?__rb_tree_red)?{?//?父節(jié)點(diǎn)為紅??
  • ????if?(x->parent?==?x->parent->parent->left)?{?//?父節(jié)點(diǎn)為祖父節(jié)點(diǎn)之左子節(jié)點(diǎn)??
  • ??????__rb_tree_node_base*?y?=?x->parent->parent->right;???//?令y?為伯父節(jié)點(diǎn)??
  • ??????if?(y?&&?y->color?==?__rb_tree_red)?{??????//?伯父節(jié)點(diǎn)存在,且為紅??
  • ????????x->parent->color?=?__rb_tree_black;???????//?更改父節(jié)點(diǎn)為黑??
  • ????????y->color?=?__rb_tree_black;??????????????//?更改伯父節(jié)點(diǎn)為黑??
  • ????????x->parent->parent->color?=?__rb_tree_red;??//?更改祖父節(jié)點(diǎn)為紅??
  • ????????x?=?x->parent->parent;??
  • ??????}??
  • ??????else?{????//?無伯父節(jié)點(diǎn),或伯父節(jié)點(diǎn)為黑??
  • ????????if?(x?==?x->parent->right)?{?//?如果新節(jié)點(diǎn)為父節(jié)點(diǎn)之右子節(jié)點(diǎn)??
  • ??????????x?=?x->parent;??
  • ??????????__rb_tree_rotate_left(x,?root);?//?第一參數(shù)為左旋點(diǎn)??
  • ????????}??
  • ????????x->parent->color?=?__rb_tree_black;???//?改變顏色??
  • ????????x->parent->parent->color?=?__rb_tree_red;??
  • ????????__rb_tree_rotate_right(x->parent->parent,?root);?//?第一參數(shù)為右旋點(diǎn)??
  • ??????}??
  • ????}??
  • ????else?{??//?父節(jié)點(diǎn)為祖父節(jié)點(diǎn)之右子節(jié)點(diǎn)??
  • ??????__rb_tree_node_base*?y?=?x->parent->parent->left;?//?令y?為伯父節(jié)點(diǎn)??
  • ??????if?(y?&&?y->color?==?__rb_tree_red)?{??????//?有伯父節(jié)點(diǎn),且為紅??
  • ????????x->parent->color?=?__rb_tree_black;???????//?更改父節(jié)點(diǎn)為黑??
  • ????????y->color?=?__rb_tree_black;??????????????//?更改伯父節(jié)點(diǎn)為黑??
  • ????????x->parent->parent->color?=?__rb_tree_red;??//?更改祖父節(jié)點(diǎn)為紅??
  • ????????x?=?x->parent->parent;????//?準(zhǔn)備繼續(xù)往上層檢查...??
  • ??????}??
  • ??????else?{????//?無伯父節(jié)點(diǎn),或伯父節(jié)點(diǎn)為黑??
  • ????????if?(x?==?x->parent->left)?{???//?如果新節(jié)點(diǎn)為父節(jié)點(diǎn)之左子節(jié)點(diǎn)??
  • ??????????x?=?x->parent;??
  • ??????????__rb_tree_rotate_right(x,?root);??//?第一參數(shù)為右旋點(diǎn)??
  • ????????}??
  • ????????x->parent->color?=?__rb_tree_black;???//?改變顏色??
  • ????????x->parent->parent->color?=?__rb_tree_red;??
  • ????????__rb_tree_rotate_left(x->parent->parent,?root);?//?第一參數(shù)為左旋點(diǎn)??
  • ??????}??
  • ????}??
  • ??}?//?while?結(jié)束??
  • ??root->color?=?__rb_tree_black;?//?根節(jié)點(diǎn)永遠(yuǎn)為黑??
  • }??
  • ?

    上述的調(diào)整函數(shù)需要左旋右旋


    __rb_tree_rotate_left():左旋

    [cpp]?view plaincopy
  • //?以下都是全域函式:__rb_tree_rotate_left(),?__rb_tree_rotate_right(),??
  • //?__rb_tree_rebalance(),?__rb_tree_rebalance_for_erase()??
  • ??
  • //?新節(jié)點(diǎn)必為紅節(jié)點(diǎn)。如果安插處之父節(jié)點(diǎn)亦為紅節(jié)點(diǎn),就違反紅黑樹規(guī)則,此時必須??
  • //?做樹形旋轉(zhuǎn)(及顏色改變,在程式它處)。??
  • inline?void???
  • __rb_tree_rotate_left(__rb_tree_node_base*?x,?__rb_tree_node_base*&?root)??
  • {??
  • ??//?x?為旋轉(zhuǎn)點(diǎn)??
  • ??__rb_tree_node_base*?y?=?x->right;?//?令y?為旋轉(zhuǎn)點(diǎn)的右子節(jié)點(diǎn)??
  • ??x->right?=?y->left;??
  • ??if?(y->left?!=0)??
  • ????y->left->parent?=?x;??????//?別忘了回馬槍設(shè)定父節(jié)點(diǎn)??
  • ??y->parent?=?x->parent;??
  • ??
  • ??//?令?y?完全頂替?x?的地位(必須將?x?對其父節(jié)點(diǎn)的關(guān)係完全接收過來)??
  • ??if?(x?==?root)????????????????????//?x?為根節(jié)點(diǎn)??
  • ????root?=?y;??
  • ??else?if?(x?==?x->parent->left)??//?x?為其父節(jié)點(diǎn)的左子節(jié)點(diǎn)??
  • ????x->parent->left?=?y;??
  • ??else??????????????????????????//?x?為其父節(jié)點(diǎn)的右子節(jié)點(diǎn)??
  • ????x->parent->right?=?y;???????????
  • ??y->left?=?x;??
  • ??x->parent?=?y;??
  • }??

  • __rb_tree_rotate_right():右旋

    [cpp]?view plaincopy
  • //?新節(jié)點(diǎn)必為紅節(jié)點(diǎn)。如果安插處之父節(jié)點(diǎn)亦為紅節(jié)點(diǎn),就違反紅黑樹規(guī)則,此時必須??
  • //?做樹形旋轉(zhuǎn)(及顏色改變,在程式它處)。??
  • inline?void???
  • __rb_tree_rotate_right(__rb_tree_node_base*?x,?__rb_tree_node_base*&?root)??
  • {??
  • ??//?x?為旋轉(zhuǎn)點(diǎn)??
  • ??__rb_tree_node_base*?y?=?x->left;??//?y?為旋轉(zhuǎn)點(diǎn)的左子節(jié)點(diǎn)??
  • ??x->left?=?y->right;??
  • ??if?(y->right?!=?0)??
  • ????y->right->parent?=?x;?????//?別忘了回馬槍設(shè)定父節(jié)點(diǎn)??
  • ??y->parent?=?x->parent;??
  • ??
  • ??//?令?y?完全頂替?x?的地位(必須將?x?對其父節(jié)點(diǎn)的關(guān)係完全接收過來)??
  • ??if?(x?==?root)????????????????????//?x?為根節(jié)點(diǎn)??
  • ????root?=?y;??
  • ??else?if?(x?==?x->parent->right)?//?x?為其父節(jié)點(diǎn)的右子節(jié)點(diǎn)??
  • ????x->parent->right?=?y;??
  • ??else??????????????????????????//?x?為其父節(jié)點(diǎn)的左子節(jié)點(diǎn)??
  • ????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)容還不錯,歡迎將生活随笔推薦給好友。