數據結構查找算法之紅黑樹

基本概念

  • 紅黑樹,本身是一棵二叉查找樹,在其基礎上附加了兩個要求:
    • 樹中的每個結點增加了一個用於存儲顏色的標誌域;
    • 樹中沒有一條路徑比其他任何路徑(指的是從任何一個結點開始,一直到其子孫的葉子結點的長度)長出兩倍,整棵樹要接近於“平衡”的狀態。
  • 紅黑樹對於結點的顏色設置不是任意的,需滿足以下性質的二叉查找樹纔是紅黑樹:
    • 樹中的每個結點顏色不是紅的,就是黑的;
    • 根結點的顏色是黑的;
    • 所有爲 nil 的葉子結點的顏色是黑的;(注意:葉子結點說的只是爲空(nil 或 NULL)的葉子結點!)
    • 如果此結點是紅的,那麼它的兩個孩子結點全部都是黑的;
    • 對於每個結點,從該結點到到該結點的所有子孫結點的所有路徑上包含有相同數目的黑結點;
    • image.png
  • 紅黑樹中每個結點都有各自的黑高度,整棵樹也有自己的黑高度,即爲根結點的黑高度,例如圖 1 中的紅黑樹的黑高度爲 3。
  • 對於一棵具有 n 個結點的紅黑樹,樹的高度至多爲:2lg(n+1)。所以紅黑樹的時間複雜度爲O(logn)

紅黑樹的旋轉

  • 旋轉操作分爲左旋和右旋,同二叉排序樹轉平衡二叉樹的旋轉原理完全相同

紅黑樹中插入新節點

  • 當創建一個紅黑樹或者向已有紅黑樹中插入新的數據時,只需要按部就班地執行以下 3 步:
    • 由於紅黑樹本身是一棵二叉查找樹,所以在插入新的結點時,完全按照二叉查找樹插入結點的方法,找到新結點插入的位置;
    • 將新插入的結點結點初始化,顏色設置爲紅色後插入到指定位置;(將新結點初始化爲紅色插入後,不會破壞紅黑樹第 5 條的性質)
    • 由於插入新的結點,可能會破壞紅黑樹第 4 條的性質(若其父結點顏色爲紅色,就破壞了紅黑樹的性質),此時需要調整二叉查找樹,想辦法通過旋轉以及修改樹中結點的顏色,使其重新成爲紅黑樹!
  • 在紅黑樹中插入結點時,根據插入位置的不同可分爲以下 3 種情況:
  1. 插入位置爲整棵樹的樹根。處理辦法:只需要將插入結點的顏色改爲黑色即可。
  2. 插入位置的雙親結點的顏色爲黑色。處理方法:此種情況不需要做任何工作,新插入的顏色爲紅色的結點不會破壞紅黑樹的性質。
  3. 插入位置的雙親結點的顏色爲紅色。處理方法:由於插入結點顏色爲紅色,其雙親結點也爲紅色,破壞了紅黑樹第 4 條性質,此時需要結合其祖父結點和祖父結點的另一個孩子結點(父結點的兄弟結點,此處稱爲“叔叔結點”)的狀態,分爲 3 種情況討論:
    • 當前結點的父節點是紅色,且“叔叔結點”也是紅色:破壞了紅黑樹的第 4 條性質,解決方案爲:將父結點顏色改爲黑色;將叔叔結點顏色改爲黑色;將祖父結點顏色改爲紅色;下一步將祖父結點認做當前結點,繼續判斷,處理結果如圖a所示
    • 當前結點的父結點顏色爲紅色,叔叔結點顏色爲黑色,且當前結點是父結點的右孩子。解決方案:將父結點作爲當前結點做左旋操作,如圖b;(在進行以父結點爲當前結點的左旋操作後,此種情況就轉變成了第 3 種情況,處理過程跟第 3 種情況同步進行)
    • 當前結點的父結點顏色爲紅色,叔叔結點顏色爲黑色,且當前結點是父結點的左孩子。解決方案:將父結點顏色改爲黑色,祖父結點顏色改爲紅色,從祖父結點處進行右旋處理。如圖c
      • 分析:在此種情況下,由於當前結點 F 和父結點 S 顏色都爲紅色,違背了紅黑樹的性質 4,此時可以將 S 顏色改爲黑色,有違反了性質 5,因爲所有通過 S 的路徑其黑高度都增加了 1 ,所以需要將其祖父結點顏色設爲紅色後緊接一個右旋,這樣這部分子樹有成爲了紅黑樹。
  • image.pngimage.pngimage.png

紅黑樹刪除節點

  • 在紅黑樹中刪除結點,思路更簡單,只需要完成 2 步操作:
    1. 將紅黑樹按照二叉查找樹刪除結點的方法刪除指定結點;
    2. 重新調整刪除結點後的樹,使之重新成爲紅黑樹;(還是通過旋轉和重新着色的方式進行調整)
  • 在二叉查找樹刪除結點時,分爲 3 種情況:
    • 若該刪除結點本身是葉子結點,則可以直接刪除;
    • 若只有一個孩子結點(左孩子或者右孩子),則直接讓其孩子結點頂替該刪除結點;
    • 若有兩個孩子結點,則找到該結點的右子樹中值最小的葉子結點來頂替該結點,然後刪除這個值最小的葉子結點。
  • 以上三種情況最終都需要刪除某個結點,此時需要判斷刪除該結點是否會破壞紅黑樹的性質。判斷的依據是:
  1. 如果刪除結點的顏色爲紅色,則不會破壞;
  2. 如果刪除結點的顏色爲黑色,則肯定會破壞紅黑樹的第 5 條性質,此時就需要對樹進行調整,調整方案分 4 種情況討論:
    • 刪除結點的兄弟結點顏色是紅色,調整措施爲:將兄弟結點顏色改爲黑色,父親結點改爲紅色,以父親結點來進行左旋操作,同時更新刪除結點的兄弟結點(左旋後兄弟結點發生了變化),如下圖所示:image.png
    • 刪除結點的兄弟結點及其孩子全部都是黑色的,調整措施爲:將刪除結點的兄弟結點設爲紅色,同時設置刪除結點的父結點標記爲新的結點,繼續判斷;
    • 刪除結點的兄弟結點是黑色,其左孩子是紅色,右孩子是黑色。調整措施爲:將兄弟結點設爲紅色,兄弟結點的左孩子結點設爲黑色,以兄弟結點爲準進行右旋操作,最終更新刪除結點的兄弟結點;
    • 刪除結點的兄弟結點是黑色,其右孩子是紅色(左孩子不管是什麼顏色),調整措施爲:將刪除結點的父結點的顏色賦值給其兄弟結點,然後再設置父結點顏色爲黑色,兄弟結點的右孩子結點爲黑色,根據其父結點做左旋操作,最後設置替換刪除結點的結點爲根結點;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章