【乾貨】幾個口訣幫你記憶紅黑樹的操作實現

kunsam發表於2019-03-11

紅黑樹是一種常用的平衡二叉樹資料結構,搜尋(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


 【紅黑樹的操作】

首先說明:我主要是總結操作實現的步驟,方便你更好的記憶,這裡並沒有放任何實現程式碼。

【插入操作】

  1. 進行平衡二叉樹插入操作
  2. 修復插入節點可能出現的違規,根據插入節點的情況分類
    1. 插入節點沒有根節點: 染黑插入節點
    2. 插入節點Parent為黑: 直接插入
    3. 插入節點Parent為紅: 根據Uncle的情況分類
      1. Uncle是紅色的: 染黑Uncle和Parent,染紅GrandParent
      2. Uncle是黑色的:
        1. 三角型: 旋轉Parent,執行直線型的操作
        2. 直線型: 旋轉GrandParent,交換插入節點與GrandParent的顏色

【插入操作口訣】

我根我爸黑,那就很簡單。
我爸要是紅,伯伯也紅,黑爸黑伯紅祖父,伯伯若黑,三角轉成直,直也轉一次,轉後祖父與兄色互換,全部結束根染黑。

【乾貨】幾個口訣幫你記憶紅黑樹的操作實現

【刪除操作】

  1. 搜尋刪除節點

  2. 查詢替換節點

  3. 刪除節點是葉節點,替換節點為null

  4. 刪除節點有一個子代,替換節點為該子代

  5. 刪除節點有兩個子代,替換節點為後繼節點(successor)

  6. 執行刪除節點,根據刪除節點和替換節點的情況分類討論

  7. 若刪除節點有兩個後代: 交換替換節點與刪除節點鍵值,對替換節點進行刪除操作

    1. 若刪除節點無兩個後代:
    2. 刪除節點是樹根: 直接刪除或替換
    3. 刪除節點是葉節點: 若刪除節點是黑色,則為雙黑,修復雙黑
    4. 刪除節點有一個後代: 若不是雙黑情況,染黑替換節點

【刪除操作口訣】

刪除節點兩後代,交換鍵值往下看。

刪除節點是樹根,直接刪除或替換。

刪除節點無後代,自己若黑修雙黑。

刪除節點有一子,若是紅子染成黑。

【乾貨】幾個口訣幫你記憶紅黑樹的操作實現

【修復雙黑操作】

什麼是雙黑和修復雙黑?

雙黑是指刪除操作中替換節點與刪除節點均為黑色的情況,雙黑標記表明了當前樹違背了黑色節點數目一致的原則,需要進行修復。修復雙黑就是為了保證紅黑樹滿足上述合法性的操作。

具體操作:

根據刪除節點的兄弟節點情況進行分類討論:

  1. 若不存在兄弟: 雙黑要傳遞給父親,對父親進行修復雙黑
  2. 兄弟是紅色: 染紅父親,染黑兄弟,把兄弟轉上去,轉化為兄弟為黑的情況
  3. 兄弟是黑色,此時需要討論兄弟兒子的情況
    1. 兄弟沒有紅色兒子,先染紅兄弟,然後討論父親顏色的情況
      1. 父親為紅色: 染黑父親即可
      2. 父親為黑色: 對父親節點修復雙黑
    2. 兄弟有紅色兒子,根據兄弟與兄弟兒子形成的結構進行分類討論
      1. 直線型: 兄弟兒子染成黑色,兄弟染成父親色,然後把兄弟轉上去
      2. 三角型: 把兄弟兒子染成和父親同色,把兄弟兒子轉到兄弟的位置,再把兄弟的兒子轉到父親的位置

【乾貨】幾個口訣幫你記憶紅黑樹的操作實現

寫在最後

我在該文章中沒有去說明實現步驟的原因和細節,因為這篇文章主要是為了提供實現操作記憶的口訣和動圖,和記憶程式碼相比,這樣更能方便記住,可以在面試筆試的時候再進行展開。

我還製作了一個關於紅黑樹的視訊,歡迎各位觀看:

https://www.bilibili.com/video/av45909616/

關於本人:我是一名工作經驗兩年多的前端,主要方向是資料視覺化和工具開發,最近離職重新學習各種計算機基礎,由於經驗不足,可能會有不少錯誤之處,如能夠指正將十分感激。


相關文章