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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

STL-红黑树源码实现

發布時間:2024/4/17 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 STL-红黑树源码实现 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

紅黑樹的介紹

它是一種特殊的二叉查找樹,紅黑樹的每個節點上都有存儲位表示節點的顏色,可以是紅或者黑。

紅黑樹的特性

1.每個節點或者黑色或者紅色

2.根節點是黑色

3.每個葉子節點是黑色

4.如果一個節點是紅色,它的子節點必須是黑色的

5.從一個節點到該節點的子孫節點的所有路徑上包含相同數目的黑節點

紅黑樹的操作

左旋

對x進行左旋,意味著“將X變為一個左節點”

右旋

平衡調節

新插入X,父節點P,G是P的父節點,S是G的另外一個子節點。

新節點x必須為葉節點,插入的節點必須為紅色;

如果P是紅色,必須調整紅色,根據X的插入位置,有4種情況:

1:S為黑色且X為外側插入,先對P,G左一次單旋轉,在更改P,G顏色,重新滿足紅黑樹的規則3:

2.S為黑且X為內側插入,先對P,X做一次單旋轉并更改G,X顏色,再將結果對G做一次單旋轉,滿足紅黑樹的規則

3.S為紅色,且X為外側插入,先對P和G做一次單旋轉,并改變X的顏色,此時,如果GG(G的父節點)為黑色,符合規則;否則,進入情況4

?

或者

4.S為紅色且X為外側插入,先對P和G做一次單旋轉,并改變X的顏色,如果G的父節點,仍然為紅色,繼續往上做,直到父子連續部位紅的情況。

或者

?

紅黑樹的實現

節點的定義

struct _Node {
?? ??? ?_Nodeptr _Left, _Parent, _Right;
?? ??? ?_Ty _Value;
?? ??? ?_Redbl _color;
?? ?};

節點的父節點,左右孩子節點

?

初始化

申請一個節點,賦值給_Nil, 并且左右子節點為0;并在構造一個節點_Head,并且設置為紅色節點,父指針指向_Nil節點,左右子節點都指向自己。

_Head節點和紅黑樹的根節點的父節點,是相互指向。

_Nil用來表示null節點。

_Lmost,指向最左邊的節點,_Rmost,指向最右邊的節點,可以用來求最小和最大值。

void _Init() {
?? ??? ?_Nodeptr _Tmp = _Buynode(0, _Black);
?? ??? ?{
?? ??? ??? ?_Lockit _Lk;
?? ??? ??? ?if (_Nil == 0) {
?? ??? ??? ??? ?_Nil = _Tmp;
?? ??? ??? ??? ?_Tmp = 0;
?? ??? ??? ??? ?_Left(_Nil) = 0, _Right(_Nil) = 0;
?? ??? ??? ?}
?? ??? ??? ?++_Nilerefs;
?? ??? ?}
?? ??? ?if (_Tmp != 0) {
?? ??? ??? ?_Freenode(_Tmp);
?? ??? ?}
?? ??? ?_Head = _Buy(_Nil, _Red), _Size = 0;
?? ??? ?_Lmost() = _Head, _Rmost() = _Head;
?? ?}

數據的插入

實現左旋

_Nodeptr _Y = _Right(_X);
?? ??? ?_Right(_X) = _Left(_Y);
?? ??? ?if (_Left(_Y) != _Nil) {
?? ??? ??? ?_Parent(_Left(_Y)) = _X;
?? ??? ?}
?? ??? ?_Parent(_Y) = _Parent(_X);
?? ??? ?if (_X == _Root()) {
?? ??? ??? ?_Root() = _Y;
?? ??? ?}
?? ??? ?else if (_X == _Left(_Parent(_X))) {
?? ??? ??? ?_Left(_Parent(_X)) = _Y;
?? ??? ?}
?? ??? ?else {
?? ??? ??? ?_Right(_Parent(_X)) = _Y;
?? ??? ?}
?? ??? ?_Left(_Y) = _X;
?? ??? ?_Parent(_X) = _Y;
?? ?}

實現右旋

void _Rrotate(_Nodeptr _X) {
?? ??? ?_Nodeptr _Y = _Left(_X);
?? ??? ?_Left(_X) = _Right(_Y);
?? ??? ?if (_Right(_Y) != _Nil) {
?? ??? ??? ?_Parent(_Right(_Y)) = _X;
?? ??? ?}
?? ??? ?_Parent(_Y) = _Parent(_X);
?? ??? ?if (_X == _Root())
?? ??? ??? ?_Root() = _Y;
?? ??? ?else if (_X == _Right(_Parent(_X))) {
?? ??? ??? ?_Right(_Parent(_X)) = _Y;
?? ??? ?}
?? ??? ?else {
?? ??? ??? ?_Left(_Parent(_X)) = _Y;
?? ??? ?}
?? ??? ?_Right(_Y) = _X;
?? ??? ?_Parent(_X) = _Y;
?? ?}

紅黑樹刪除

紅黑樹的刪除分為兩種情況,情況1是有兩個子的情況,情況2最多有一個子樹的情況

?_Nodeptr _X;
?? ??? ?_Nodeptr _Y = (_P++)._Mynode();
?? ??? ?_Nodeptr _Z = _Y;

_Y:表示的是要刪除的節點,_P表示的是臨近_Y的大的節點

_Z:賦值為_Y

情況1:最多有一個子樹的情況

  • ? ?如果左子樹或者右子樹為空的情況? ?

if (_Left(_Y) == _Nil) {
?? ??? ??? ?_X = _Right(_Y);
?? ??? ?}
?? ??? ?else if (_Right(_Y) == _Nil) {
?? ??? ??? ?_X = _Left(_Y);
?? ??? ?}

?

把_X分別設置為右子樹和左子樹。

  • 然后把_X的父節點,設置為_Y的父節點即可;

? ? ? _Parent(_X) = _Parent(_Y);

  • 特殊情況判斷,如果為root()節點

if (_Root() == _Z)
?? ??? ??? ??? ?_Root() = _X;

否則就設置_Z的左右子樹

else if (_Left(_Parent(_Z)) == _Z) {
?? ??? ??? ??? ?_Left(_Parent(_Z)) = _X;
?? ??? ??? ?}
?? ??? ??? ?else {
?? ??? ??? ??? ?_Right(_Parent(_Z)) = _X;
?? ??? ??? ?}

  • 判斷是否為_Lmost??

if (_Lmost() != _Z) {
?? ??? ??? ??? ?;
?? ??? ??? ?}

如果_Z是_Lmost就把_Z的父節點,設置為_Lmost
?? ??? ??? ?else if (_Right(_Z) == _Nil) {
?? ??? ??? ??? ?_Lmost() = _Parent(_Z);
?? ??? ??? ?}
?? ??? ??? ?else {
?? ??? ??? ??? ?_Lmost() = _Min(_X);
?? ??? ??? ?}

_Rmost的判斷是同樣的。

情況2:有兩個子樹的情況


?? ??? ??? ?_Y = _Min(_Right(_Y));
?? ??? ??? ?_X = _Right(_Y);

去_Y的右子樹的最小節點,然后把_X置為該節點的右數,_Z是要刪除的節點。目的是把_Y這個節點,放到_Z的位置上去;接下來就是要調整,_Z,_Y的左右子樹和父節點的指向。

  • 更新_Z的左右子樹的父節點的指向為_Y

_Parent(_Left(_Z)) = _Y;

  • 更新_Y的左子樹的指向為_Z的左子樹的指向

?_Left(_Y) = _Left(_Z);

  • 如果恰好_Y==_Right(_Z)

if (_Y == _Right(_Z)) {
?? ??? ??? ??? ?_Parent(_X) = _Y;
?? ??? ??? ?}

  • 否則

? ? ? ? ? ? ? ? ? ? _Parent(_X) = _Parent(_Y);
?? ??? ??? ??? ??? ?_Left(_Parent(_Y)) = _X;
?? ??? ??? ??? ??? ?_Right(_Y) = _Right(_Z);
?? ??? ??? ??? ??? ?_Parent(_Right(_Z)) = _Y;

刪除后平衡調整

如果刪除的是黑色節點,才需要進行平衡調整。

分析左子樹的情況:

while (_X != _Root() && _Color(_X) == _Black) {
?? ??? ??? ??? ?if (_X == _Left(_Parent(_X))) {

  • 獲取_X節點的父節點的右子樹

_Nodeptr _W = _Right(_Parent(_X));

  • 如果_W的顏色是紅色

_Color(_W) = _Black;
?? ??? ??? ??? ??? ??? ?_Color(_Parent(_X)) = _Red;
?? ??? ??? ??? ??? ??? ?_Lrotate(_Parent(_X));
?? ??? ??? ??? ??? ??? ?_W = _Right(_Parent(_X));

if (_Color(_Left(_W)) == _Black&&_Color(_Right(_W)==_Black) {
?? ??? ??? ??? ??? ??? ?_Color(_W)=_Red;
?? ??? ??? ??? ??? ??? ?_X=_Parent(_X);
?? ??? ??? ??? ??? ?}
?? ??? ??? ??? ??? ?else {
?? ??? ??? ??? ??? ??? ?if (_Color(_Right(_W)) == _Black) {
?? ??? ??? ??? ??? ??? ??? ?_Color(_Left(_W))=_Black;
?? ??? ??? ??? ??? ??? ??? ?_Color(_W)=_Red;
?? ??? ??? ??? ??? ??? ??? ?_Rrotate(_W);
?? ??? ??? ??? ??? ??? ??? ?_W=_Right(_Parent(_X));
?? ??? ??? ??? ??? ??? ?}
?? ??? ??? ??? ??? ??? ?_Color(_W) = _Color(_Parent(_X));
?? ??? ??? ??? ??? ??? ?_Color(_Parent(_X)) = _Black;
?? ??? ??? ??? ??? ??? ?_Color(_Right(_W)) = _Black;
?? ??? ??? ??? ??? ??? ?_Lrotate(_Parent(_X));
?? ??? ??? ??? ??? ??? ?break;

?? ??? ??? ??? ??? ?}

總結

以上是生活随笔為你收集整理的STL-红黑树源码实现的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。