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為紅色時需要調整樹形!!!插入節點分為以下情況:p:父節點
s:伯父節點(父節點的兄弟節點)
g:祖父節點
gg:曾祖父節點
父節點是紅色,伯父節點也是黑色(或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...