數據結構與算法系列第三篇——樹(紅黑樹)

二叉搜索樹引入的問題

如果樹中插入的是隨機數據,則執行效果很好。但是,如果插入的是有序的數據的數據,速度就會變得特別慢。**因爲當插入的數值有序時,二叉搜索樹就退化成了鏈表的形式了。**此時,也可以說這棵樹是非平衡樹,那麼它的快速查找(插入,刪除)指定數據項的能力就喪失了。
如下圖所示:
在這裏插入圖片描述

平衡樹和非平衡樹

平衡樹,即平衡二叉樹(Balanced Binary Tree),具有以下性質:它是一棵空樹或它的左右兩個子樹的高度差的絕對值不超過1,並且左右兩個子樹都是一棵平衡二叉樹
圖9-1是一種極端不平衡的樹,它的事件複雜度爲O(N)。所以搜索部分非平衡樹的時間介於O(N)和O(logN)之間,這取決於樹的不平衡程序。

非平衡樹的補救措施

在插入過程中,對於一個要插入的數據項,插入例程要檢查不會破壞樹一定的特徵。如果破壞了,程序就會進行糾正,根據需要更改樹的結構。通過維持樹的特徵,保證了樹的平衡。我們將這種方式成爲旋轉

紅黑樹

紅黑樹是一種自平衡的二叉搜索樹
它的規則如下:

  • 1.每一個節點不是紅色就是黑色
  • 2.根總是黑色的
  • 3.如果節點是紅色的,則它的子節點必須是黑色的
  • 4.從根到葉節點或空子節點的每條路徑,必須包含相同數量的黑色節點。

紅黑樹的修正措施

  • 改變節點的顏色
  • 執行旋轉操作

紅黑規則和平衡樹

在這裏插入圖片描述
爲什麼紅黑規則能保證樹是平衡的?
如果一條路徑上的節點數比另一條路徑上的節點數多一個以上(不包含1個),那它要麼有更多的黑色節點,違背了規則4。要麼有兩個相鄰接的紅色節點,違背了規則3。

空子節點

如果節點只有右子節點,那麼它的空缺的左子節點就是空子節點。反之亦然。
如下圖所示:
在這裏插入圖片描述
在這裏插入圖片描述

旋轉

旋轉要做的兩件事情:

  • 使一些節點上升,一些節點下降,幫助樹平衡
  • 保證不破壞二叉搜索樹的特徵

簡單旋轉

向左旋轉或者向右旋轉
選擇一個節點作爲旋轉的“頂端”。如果做一次右旋,這個“頂端”節點將會向下和向右移動到它右子節點的位置。它的左子節點將會上移到它原來的位置。
注意事項:
如果做右旋,頂端節點必須有一個左子節點。否則,將沒有節點旋轉到頂端節點原來所在的位置。類似,左旋,頂端節點必須有一個右子節點。

橫向移動節點

在這裏插入圖片描述

移動子樹

在這裏插入圖片描述
在這裏插入圖片描述

  • 頂端節點(50)移動到它右子節點的位置
  • 頂端節點的左子節點(25)移動到頂端的位置上
  • 以節點12爲根的整棵子樹都向上移動
  • 以節點37爲根的整棵子樹橫向移動,成爲節點50的左子節點
  • 以節點75爲根的整棵子樹都向下移動

紅黑樹插入一個新節點

需要解決以下三個問題:

  • 在下行路途中的顏色變換
  • 插入節點之後的旋轉
  • 在向下路途中的旋轉。

在下行路途中的顏色變換

紅黑樹的插入例程的開始時所做的事情和普通的二叉搜索樹所做的基本一樣:沿着根朝插入點位置走,在每一個節點處通過比較節點的關鍵字相對大小來決定向左走還是向右走。
查找插入新節點的位置,爲了不違反顏色規則,在必要的時候需要進行顏色變換。
規則:每當查找例程遇到一個有兩個紅色子節點的黑色節點時,它必須把子節點變爲黑色,而把父節點變爲紅色(除非父節點爲根節點,根總是黑色的)
如下圖所示:
在這裏插入圖片描述
這種顏色變換之後帶來的好處:

  • 黑色高度不改變
  • 對根的兩個子節點做顏色變換,根和它的兩個子節點一樣都是黑色的。這樣不違背規則2,3,4
    這種顏色變換之後也帶來了新問題:
    如果P的父是黑色的,則P由黑色變成紅色不會有問題。但是,如果P的父節點是紅色的,那麼,在P的顏色變化之後,就有兩個紅色節點相連接了,違背了規則3.

插入節點之後的旋轉

新數據項的插入可能會違背紅黑規則,因此,在插入之後,必須要檢測是否違背規則,並採用相應的措施。
如下圖所示,有四種情況
在這裏插入圖片描述
如果節點X在P的一側與P在G的一側相同,則X就是一個外側子孫節點。相反,如果節點X在P的一側,而P在G的另一側,則X就是一個內側子孫節點。
有了上述概念之後,四種情況歸納爲三種:
新插入的X總是紅色的

  • 1.P是黑色的
  • 2.P是紅色的,X是G的一個外側子孫節點
  • 3.P是紅色的,X是G的一個內側子孫節點

可能性1:P是黑色的

如果P是黑色,什麼事情也不用做。因爲剛剛插入的節點總是紅色的。如果它的父節點是黑色,則沒有紅色節點連接紅色節點的衝突(規則3)。並且也不會增加黑色節點的數目(規則4)。因此,不需要做其他事情,插入完成。

可能性2:P是紅色的,X是G的一個外側子孫節點

在這裏插入圖片描述
改變X的祖父節點G(25)的顏色
在這裏插入圖片描述
改變X的父節點P(12)的顏色
在這裏插入圖片描述
以X的祖父節點G(25)爲頂旋轉,向X(6)上升的方向。做一次右旋操作
在這裏插入圖片描述

可能性3:P是紅色的,X是G的一個內側子孫節點

如下圖所示:
在這裏插入圖片描述
當X(18)是內側子孫節點時,其解決技巧是執行兩次旋轉。第一次把X由內側子孫節點變爲外側子孫節點。再按照 外側子孫節點的情況進行處理。
操作步驟如下(一般是先着色,再旋轉):

  • 1.改變X的祖父節點(25)的顏色
    在這裏插入圖片描述
  • 2.改變X(18)的顏色
    在這裏插入圖片描述
  • 3.用X的父節點P作爲頂旋轉,向左旋轉。
    在這裏插入圖片描述
    在這裏插入圖片描述
  • 4.再以X的祖父節點(25)爲頂旋轉,右旋
    在這裏插入圖片描述
    在這裏插入圖片描述

在下行路途中的旋轉

在下行路途中查找插入點時所做的旋轉
在向下的路徑上有兩種旋轉的可能性,分別對應前面描述的在插入階段的可能性2和可能性3。違背規則的節點可能是一個外側子孫節點,也可能是一個內側子孫節點。

外側子孫節點

在這裏插入圖片描述
注意:在插入12和6時已經做了兩次顏色變換,否則不能插入新節點
現在要插入值爲3的節點。必須對節點12以及它的子節點6和18做顏色變換。
變換後如下圖:
在這裏插入圖片描述
糾正這種違規情況和前面討論的插入的可能情況2類似。必須要執行兩次顏色變換和一次旋轉。
以剛剛做了顏色變換三角形的頂端節點爲X(12),P(25),G(50)

  • 1.改變X的祖父節點G(50)的顏色。
    在這裏插入圖片描述
  • 2.改變X的父節點(25)的顏色
    在這裏插入圖片描述
  • 3.以X的祖父節點G(50)爲頂旋轉,做右旋操作。
    在這裏插入圖片描述
    糾正之後,就可以插入3了

在這裏插入圖片描述

內側子孫節點

在這裏插入圖片描述
插入一個新節點28,需要顏色變換。此時25和37都是紅色。G(50),P(25),X(37)

在這裏插入圖片描述
爲了解決紅-紅衝突。需要做和可能性3相同的兩次顏色變換和兩次旋轉。

  • 1.改變G(50)的顏色
    在這裏插入圖片描述
  • 2.改變X(37)的顏色
    在這裏插入圖片描述
  • 3.以P(25)爲頂旋轉,左旋
    在這裏插入圖片描述
  • 4.以G(50)爲頂旋轉,右旋
    在這裏插入圖片描述
    可以插入28了,當插入它之前顏色變換把25和50都變爲黑色(未理解)
    在這裏插入圖片描述

結論

在插入的過程中,保證樹的紅黑特性,可以取得樹的平衡

刪除

在普通二叉搜索樹中編寫刪除操作的代碼比編寫插入操作要難得多。在紅黑樹也是這樣的,並且在刪除過程由於需要在節點刪除之後恢復樹的紅黑正確性,變得更復雜。
由於刪除的複雜性,在實際操作中都是規避真正的刪除節點。就是爲刪除的節點做個標記而不實際的刪除它。任何找到該節點的查找例程都知道不用報告已找到該節點

紅黑樹的效率

紅黑樹的查找,插入和刪除的時間複雜度爲O(logN)。在紅黑樹的查找時間和在普通的二叉搜索樹查找時間幾乎一樣,因爲在查找的過程中並沒有應用到紅黑樹的特徵,額外的開銷只是每一個節點的存儲空間都稍微增加了一點,來存儲紅黑樹的顏色(boolean變量)。
插入和刪除的時間要增加一個常數因子,因爲不得不在下行的路徑上和插入點執行顏色變換和旋轉。平均起來,一次插入大約需要一次旋轉。因此,插入的時間複雜度還是O(logN),但是比普通的二叉搜索樹要慢。
大多數應用中,查找的數次比插入和刪除的次數多,所以使用紅黑樹取代普通的二叉搜索樹總體不會增加太多的時間開銷。
紅黑樹的優點是對有序數據的操作不會慢到O(N)的時間複雜度

其他平衡樹

AVL樹:在AVL樹中,每個節點存儲一個額外的數據,它的左子樹和右子樹的高度差,這個差值不會大於1.也就是說,節點的左子樹的高度和右子樹的高度相差不會大於1層。
插入之後,檢查新節點的插入點所在的最低子樹的根。如果它的子節點的高度相差大於1,執行一次或者兩次旋轉使它們的高度相同。然後算法上移,檢查上面的節點,必要時均衡高度。這個檢測檢查所有路徑一直向上,直到根爲止。
AVL樹查找的時間複雜度爲O(logN),因爲樹一定是平衡的。但是,由於插入(刪除)一個節點需要掃描兩趟樹,一次向下查找插入點,一次向上平衡樹,所以:
AVL樹不如紅黑樹效率高,也不如紅黑樹常用。

小結

  • 保持二叉搜索樹的平衡是爲了查找給定節點所需要的時間儘可能的短
  • 插入有序的數據將創建最不平衡的樹,它的查找時間複雜度爲O(N)
  • 在紅黑平衡的方法中,每個節點的顏色不是紅的就是黑的
  • 紅黑樹的4大規則(背誦並理解)
    • 節點不是紅的就是黑的
    • 根節點必須爲黑色
    • 紅色節點的子節點一定爲黑色
    • 從根到各個葉子節點(空子節點)的黑色節點的數目是相等的
  • 插入或者刪除一個節點時應用這些規則
  • 一次顏色變換把一個黑色節點和它的兩個紅色子節點改爲一個紅色節點和兩個黑色子節點
  • 在一次旋轉中,指定一個節點爲頂端節點
  • 右旋把頂端節點移動到它的右子節點的位置,並把頂端節點的左子節點移動到頂端節點的位置
  • 左旋是把頂端節點移動到它的左子節點的位置,並把頂端節點的右子節點移動到頂端節點的 位置
  • 當順着樹向下查找新節點的插入位置時,應用顏色變換,並且有時應用旋轉。顏色變換通過簡單的方法,就使樹在插入後恢復成正確的紅黑樹
  • 新節點插入後,檢查紅紅衝突。如果發現違背紅黑規則現象,執行適當的旋轉使樹恢復紅黑正確性
  • 在二叉樹中加入紅黑平衡對平均執行效率只有很小的負面影響,然而卻避免了對有序的數據操作的最壞的性能。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章