STL原始碼剖析 容器 RB tree

2022-06-05 19:54:10 字數 3862 閱讀 2048

rb tree,全稱是red-black tree,又稱為「紅黑樹」。紅黑樹本質上是一種二叉查詢樹,但它在二叉查詢樹的基礎上額外新增了乙個標記(顏色),同時具有一定的規則。這些規則使紅黑樹保證了一種平衡,插入、刪除、查詢的最壞時間複雜度都為o(logn)

每個節點不是紅色就是黑色

根結點永遠都是黑色

所有葉節點都是黑色(注意這裡說葉子節點其實是上圖中的nil節點)

父子節點不同為紅色

從任一節點到其子樹中每個葉子節點的r任一路徑都包含相同數量黑色節點

注意

性質(3)中的葉子節點,是只為空(nil或null)的節點。

性質(5),確保沒有一條路徑會比其他路徑長出倆倍。因而,紅黑樹是相對是接近平衡的二叉樹。

簡略記憶:「右子變老子」左旋中的「左」,意味著「被旋轉的節點將變成乙個左節點」。如圖所示

旋轉點右孩子的左子樹(b)變成旋轉點的右子樹

旋轉點右孩子頂替旋轉點位置

修改旋轉點與右孩子關係

* 左旋 右子節點變為父節點(原父節點變為右子節點的左節點)

*/inline void

_rb_tree_rotate_left(_rb_tree_node_base* __x, _rb_tree_node_base*& __root)

簡略記憶:「左子變老子」右旋中的「右」,意味著「被旋轉的節點將變成乙個右節點」。如圖所示

旋轉點左孩子的右子樹(b)變成旋轉點的左子樹

旋轉點左孩子頂替旋轉點位置

修改旋轉點與右孩子關係

* 右旋 左子節點變為父節點(原父節點變為左孩子的右孩子)

*/inline void

_rb_tree_rotate_right(_rb_tree_node_base* __x, _rb_tree_node_base*& __root)

紅黑樹的插入操作主要步驟如下:

假設:

x:新節點(預設紅色

p:父節點

s:伯父節點(父節點的兄弟節點)

g:祖父節點

gg:曾祖父節點

強調:只有當父節點p為紅色時需要調整樹形!!!插入節點分為以下情況:

父節點是紅色,伯父節點也是黑色(或nil),祖父節點必定是黑色。

父子節點同側,即,子節點、父節點、以及祖父節點是直線型。

父節點、祖父節點變色(父節點變為黑色,祖父節點變為紅色)

單旋,以祖父節點為旋轉點

父節點是紅色,伯父節點也是黑色(或nil),祖父節點必定是黑色。

父子節點異側,即,子節點、父節點、以及祖父節點是非直線型。

單旋,以父節點為旋轉點

父節點作為「新節點」

狀況3:父紅,伯黑(或nil),父子同側繼續處理

父節點是紅色,伯父節點也是紅色,祖父節點必定是黑色。

變色

祖父節點作為「新節點」

向上繼續調整:

3.1 曾祖父節點為黑色,結束

3.2 當前新節點為,直接設定成黑色,結束

3.3 曾祖父節點為紅色,所屬狀況,繼續調整樹形

/* 狀況3:父(左)紅,伯(右)黑(或nil),新節點為左子 */

__x->_m_parent->_m_color = _s_rb_tree_black;

__x->_m_parent->_m_parent->_m_color = _s_rb_tree_red;

_rb_tree_rotate_right(__x->_m_parent->_m_parent, __root);}}

else

else

/* 狀況3:父(右)紅,伯(左)黑(或nil),新節點為右子 */

__x->_m_parent->_m_color = _s_rb_tree_black;

__x->_m_parent->_m_parent->_m_color = _s_rb_tree_red;

_rb_tree_rotate_left(__x->_m_parent->_m_parent, __root);}}

} __root->_m_color = _s_rb_tree_black; // 根節點設定為黑色

}紅黑樹可以看成是具有特殊性質的二叉查詢樹,因此紅黑樹的刪除過程可分為兩步:

二叉查詢樹的刪除分為以下情況:

刪除節點是葉子節點,直接刪除;

刪除節點只有左孩子(或右孩子),孩子節點替代刪除節點位置;

刪除節點有兩個孩子,選擇乙個合適的子孫節點替代刪除節點位置,該節點稱為繼承節點

按照二叉查詢樹的規則刪除節點後,還需要檢查是非滿足紅黑樹的性質。

根據紅黑樹的性質,主要是性質4)父子節點不同為紅色,性質5)從任一節點到其子樹中每個葉子節點的r任一路徑都包含相同數量黑色節點。

待補充。。。

重溫資料結構:深入理解紅黑樹

紅黑樹(一)之 原理和演算法詳細介紹

STL原始碼剖析 容器 vector

vector 常被稱為向量容器,因為該容器擅長在尾部插入或刪除元素,在常量時間內就可以完成,時間複雜度為o 1 而對於在容器頭部或者中部插入或刪除元素,則花費時間要長一些 移動元素需要耗費時間 時間複雜度為線性階o n vector實現的關鍵在於其對大小的控制以及重新配置時的資料移動效率。vecto...

STL原始碼剖析 關聯式容器

一 set 所有元素都會根據元素的鍵值自動排序,set元素不像map那樣可以同時擁有key和value,set元素的鍵值就是實值,set不允許有兩個相同元素的鍵值。二 map 所有元素都會根據元素的鍵值自動排序,map不允許有兩個元素有相同的鍵值。以紅黑樹作為底層機制,每乙個節點上的內容是乙個pai...

《STL原始碼剖析》 序列式容器

stl原始碼剖析 前言 所謂的序列式容器,其中的元素都可序,但未必有序,c 本身提供了乙個序列式容器array,stl 提供了vector,list,deque,srack,queue,priority queue等 一.使用reverse 函式提前設定容量大小 1.1 提前設定的原因 對於vect...