紅黑樹是一種常用的平衡二叉樹資料結構,搜尋(search)、插入(insertion)和刪除(deletion)的時間複雜度為O(Logn)。
用於C++實現Map/Set, Java實現TreeMap/HashMap等資料結構,此外還可以用於實時計算程式和函數語言程式設計中。
【紅黑樹的性質】
- 根節點總為黑色。Root of tree is always black
- 不存在相鄰的紅色節點。There are no two adjacent red nodes
- 從任何一個節點出發到它的任何一個NULL葉節點的所有路徑,經過的黑色節點數量之和相同。Every path from a node (including root) to any of its descendant NULL node has the same number of black nodes
Features
- 每個紅黑樹的高度: h ≤ 2Log2(n+1)
- 每個紅黑樹的黑色節點數: Nblack ≥ n / 2
- The height of a Red-Black tree is always O(Logn)
- 任何一個節點到葉節點的黑色節點數(Black Height): BH >= h/2.
- There is a root to leaf path with at-most Log2(n+1) black nodes
【紅黑樹的操作】
首先說明:我主要是總結操作實現的步驟,方便你更好的記憶,這裡並沒有放任何實現程式碼。
【插入操作】
- 進行平衡二叉樹插入操作
- 修復插入節點可能出現的違規,根據插入節點的情況分類
- 插入節點沒有根節點: 染黑插入節點
- 插入節點Parent為黑: 直接插入
- 插入節點Parent為紅: 根據Uncle的情況分類
- Uncle是紅色的: 染黑Uncle和Parent,染紅GrandParent
- Uncle是黑色的:
- 三角型: 旋轉Parent,執行直線型的操作
- 直線型: 旋轉GrandParent,交換插入節點與GrandParent的顏色
【插入操作口訣】
我根我爸黑,那就很簡單。
我爸要是紅,伯伯也紅,黑爸黑伯紅祖父,伯伯若黑,三角轉成直,直也轉一次,轉後祖父與兄色互換,全部結束根染黑。
【刪除操作】
-
搜尋刪除節點
-
查詢替換節點
-
刪除節點是葉節點,替換節點為null
-
刪除節點有一個子代,替換節點為該子代
-
刪除節點有兩個子代,替換節點為後繼節點(successor)
-
執行刪除節點,根據刪除節點和替換節點的情況分類討論
-
若刪除節點有兩個後代: 交換替換節點與刪除節點鍵值,對替換節點進行刪除操作
-
- 若刪除節點無兩個後代:
- 刪除節點是樹根: 直接刪除或替換
- 刪除節點是葉節點: 若刪除節點是黑色,則為雙黑,修復雙黑
- 刪除節點有一個後代: 若不是雙黑情況,染黑替換節點
【刪除操作口訣】
刪除節點兩後代,交換鍵值往下看。
刪除節點是樹根,直接刪除或替換。
刪除節點無後代,自己若黑修雙黑。
刪除節點有一子,若是紅子染成黑。
【修復雙黑操作】
什麼是雙黑和修復雙黑?
雙黑是指刪除操作中替換節點與刪除節點均為黑色的情況,雙黑標記表明了當前樹違背了黑色節點數目一致的原則,需要進行修復。修復雙黑就是為了保證紅黑樹滿足上述合法性的操作。
具體操作:
根據刪除節點的兄弟節點情況進行分類討論:
- 若不存在兄弟: 雙黑要傳遞給父親,對父親進行修復雙黑
- 兄弟是紅色: 染紅父親,染黑兄弟,把兄弟轉上去,轉化為兄弟為黑的情況
- 兄弟是黑色,此時需要討論兄弟兒子的情況
- 兄弟沒有紅色兒子,先染紅兄弟,然後討論父親顏色的情況
- 父親為紅色: 染黑父親即可
- 父親為黑色: 對父親節點修復雙黑
- 兄弟有紅色兒子,根據兄弟與兄弟兒子形成的結構進行分類討論
- 直線型: 兄弟兒子染成黑色,兄弟染成父親色,然後把兄弟轉上去
- 三角型: 把兄弟兒子染成和父親同色,把兄弟兒子轉到兄弟的位置,再把兄弟的兒子轉到父親的位置
- 兄弟沒有紅色兒子,先染紅兄弟,然後討論父親顏色的情況
寫在最後
我在該文章中沒有去說明實現步驟的原因和細節,因為這篇文章主要是為了提供實現操作記憶的口訣和動圖,和記憶程式碼相比,這樣更能方便記住,可以在面試筆試的時候再進行展開。
我還製作了一個關於紅黑樹的視訊,歡迎各位觀看:
https://www.bilibili.com/video/av45909616/
關於本人:我是一名工作經驗兩年多的前端,主要方向是資料視覺化和工具開發,最近離職重新學習各種計算機基礎,由於經驗不足,可能會有不少錯誤之處,如能夠指正將十分感激。