標籤:img 技術分享 一個 相同 margin 代碼 方向 介紹 str
本篇部落格我會重點介紹對紅-黑樹的理解,重點介紹紅-黑樹的尋找,這裡我們將要討論的演算法稱為自頂向下插入,也就是把沿著樹向下尋找插入點
Ⅰ、平衡樹和非平衡樹
平衡樹和非平衡樹:當插入一組資料關鍵字是按照升序或者降序插入的話此時就是集中最極端的不平衡樹,此時也可看做是一個鏈表此時對於此樹的尋找的時間複雜度為O(N),所以搜尋不平衡樹的時間複雜度介於平衡樹時間複雜度O(logN)和O(N)之間時間具體取決於樹的不平衡度。
Ⅱ、紅-黑樹規則
接下來我們要討論的紅-黑樹具有以下幾個特徵(紅-黑樹規則):
- 1.每一個節點不是紅色就是黑色
- 2.根總是黑色的
- 3.若節點是紅色的,則它的子節點必須全是黑色的(反過來就不一定成立)
- 4.從根到分葉節點或空子節點的每一條路徑必須包含相同數目的黑色節點
第四條中的“空子節點”指的是有右子節點的節點可能接左子節點的位置,或者說有左子節點的節點可能接右子節點的位置。就是非分葉節點本可能有,但是實際上沒有的那個子節點(若節點只有右子節點,那麼空缺的左子節點就是空子節點,反之亦然)中50→25→25的右子節點(空子節點)黑色高度為1,從根到6以及到75的黑色節點數都為2,這樣就違背了規則4,此樹到分葉節點的黑色節點數相同,但是有一個空子節點的黑色節點數為1所以此樹不是紅-黑樹。
從根節點到分葉節點路徑上面的黑色節點數目稱為黑色高度,所以上面的規則四的另一種陳述方法是:所有從根到分葉節點路徑上的黑色高度必須相同。
為了滿足紅/黑樹狀結構規則我們可能會使用到下面兩種方式來進行修正,從而使一棵樹滿足紅/黑樹狀結構規則,
- 改變節點顏色
- 執行旋轉操作
為什麼保證上面四個紅-黑樹規則就能保證紅-黑樹是平衡樹呢?從紅/黑樹狀結構規則分析我們可以得到若一棵樹超過了兩層不平衡怎這棵樹則不可能滿足紅-黑樹規則,超過兩層不平衡則表明有路徑的節點數比另外的路徑的節點數多一個以上,多出來的要麼有更多的黑色節點,若這樣則違背了紅-黑樹規則4,要麼至少有兩個相鄰接的紅色節點,這樣就違背了紅色節點的子節點必須全部是黑色節點。
Ⅲ、樹的旋轉:
利用樹的旋轉來重新排列一些節點,來平衡一棵樹,旋轉必須要做到兩件事情:
- 使一些節點上升,一些節點下降,協助樹平衡
- 保證不破壞二叉搜尋樹的特徵(由於搜尋演算法依賴此特徵,不然就沒意義)
上面利用紅/黑樹狀結構的色彩規則和節點的顏色變化只是有助於決定何時執行旋轉。光改變顏色並不能讓分樹達到平衡,旋轉才是讓樹平衡的關鍵操作,所以我們要好好理解樹的旋轉操作;做旋轉的時候要注意做右旋頂點必須要有一個左子節點,左旋頂端必須要有右子節點,不然旋轉後頂點會沒有節點,接下來我們看的一個簡單的旋轉:
中a→b我們可以看到該樹進行了一次右旋,a圖中節點37稱為頂端節點50的內側子孫(節點12是外側子孫點),對內側子孫而言,如果他是上移的節點的子節點,它就必須要斷開和父節點的串連並且重新串連到它以前的爺爺節點之上,就好像自己成為了自己的叔叔一樣。是旋轉過程中單節點的位置變換,上面我們說的內側子孫也可以是一棵子樹,我們展示了假如是子樹的節點的一個移動情況,大致的原理差不多是相通的。
中的樹進行了一次右旋,做了以下幾個事情:
- 頂端節點(50)移動到他右子節點的位置
- 頂端節點的左子節點(25)移動到頂端的位置上
- 以節點12為根的整棵子樹都向上移動
- 因節點為37為根的整棵子樹橫向移動,成為節點50的左子節點
- 以節點75為根的整棵子樹向下移動
上面我們看到了旋轉一棵樹要進行怎麼樣的旋轉,接下來我們討論如何插入一個新節點(利用旋轉和色彩規則來保持樹的平衡)
Ⅳ、節點的插入
在我們向下尋找插入點的時候我們主要討論一下三個方面
- 下行途中的顏色變化
- 向下路途上的旋轉
- 插入節點後的旋轉
① 下行途中的顏色變化
首先我們討論下行途中的顏色變化尋找的方式和普通的二叉搜尋樹是一樣的,只是在下行的途中會涉及到顏色的變化,規則如下:每當遇到一個有兩個紅色子節點的黑色節點時,它必須把子節點變為黑色,把父節點變為紅色(除非父節點為根節點),如就進行了一次顏色變換
中進行顏色變化沒有改變從根向下過P到分葉節點或空子節點路徑上的黑色節點的數目因此顏色變換並沒有違反規則4,這樣變化的好處是在不違背規則3的情況下串連新的紅色節點更容易。上面顏色變化雖然不會違背規則4但是有可能違背規則3,若中P節點的父節點是紅色,那麼變換之後就違背了規則3,那麼此時就會對樹進行旋轉操作,
② 在向下的路徑上的旋轉
向下路徑上的旋轉有兩種可能性,當違背的節點是外側的子孫節點“違背規則的節點”是指在造成紅紅衝突的父子節點對中的子節點,我們從50開始建立一棵新樹插入以下節點:25,75,12,37,6和18在插入12和6的時候需要做顏色變換。接下來我們要插入節點3,必須對節點12以及它的子節點6和18做顏色變換,此時產生的樹就是中的a樹,此時節點25和12違背了紅/黑樹狀結構規則3,此時需要對此樹進行旋轉的操作,
這裡我們設剛剛進行顏色變換的三角形的頂點為X,X的父節點為p,祖父節點為G,此時我們對中的a進行如下的顏色變化和旋轉:
- 改變X的祖父節點P的顏色(本例中旋轉後還必須要改變根的顏色)
- 改變X父節點P的顏色
- 以X的祖父節點G為頂旋轉,向X上升的方向旋轉
這樣 就滿足了紅-黑樹的色彩規則,樹就成為了一棵平衡樹,此時就能很容易地插入節點3,插入之後如中的b圖所示。
若插入的是內側的子孫節點,此時我們以根為50,插入25,75,12,37,31和43.在插入12和31之前需要顏色變換,然後新插入節點28,向下尋找插入點的時候,在37節點的時候需要執行顏色變換,變換後如的a樹所示,變換後25和37都是紅色需要進行旋轉操作,此時顏色變換三角形的頂點X為37,P為25,G為50,執行以下四步使樹從新平衡
- 改變G的顏色
- 改變X的顏色
- 以P為頂旋轉向X上升的方向旋轉,旋轉結果如b所示
- 以G為頂旋轉,X上升方向旋轉,旋轉後即可輕鬆插入節點28
③ 插入節點之後的旋轉
接下來我們討論插入節點之後的旋轉,這裡我們討論插入的節點為X,其父節點為P,祖父節點為G。1.若節點X在P的一側與P在G的一側相同,則X就是一個外側的子孫節點(a,d),反之若不相同則X是一個內側子孫節點(b,c)。顯示了”指向“左右變化的多樣性
為恢複紅黑規則所執行的操作是由X和它的親屬所決定的,節點只以三種當時排列(上面的指向變換不算在內)
- P是黑色的。
- P是紅色的,X是G的一個外側子孫節點
- P是紅色的X是G的一個內側的子孫節點,如所示
可能性1:若P是黑色的 :不需要做任何事情,由於插入的節點總是紅色的。若父節點是黑色的,則 沒有紅色節點串連紅色節點衝突也不會增加黑色節點數目,所以此時插入不需要做任何事情。
可能性2:P是紅色,X是G的一個外側子孫節點:這是插入後需要一次旋轉和一些顏色變化,此時我們可以建立一個根為50的樹,然後插入25,75和12。在插入12之前需要做一次顏色變換,然後向該樹中插入6,得到中的a樹,此時違背了紅/黑樹狀結構規則,需要進行一下三個步驟的變換,
- 改變X的祖父節點G的顏色。
- 改變X父節點P的顏色。
- 以X的祖父節點G為頂旋轉,方向為X的上升方向,變換後的樹如中的b,再次成為一棵紅/黑樹狀結構
可能性3:P是紅色的X是G的一個內側的子孫節點,這時需要做兩次旋轉和一些顏色改變,首先我們建立一顆節點為50,25,75,12,18的樹(在插入節點12之前需要一次顏色變換)插入12後的樹如a所示,插入節點18是一個內側子孫節點,他和他的父節點都是紅色,首先第一次旋轉將子孫節點變為外側子孫節點,中的b->c然後就可以利用同情況1相同的旋轉,色彩轉換和旋轉的步驟如下:
- 改變X的祖父節點25的顏色
- 改變X節點18的顏色
- 用X的父節點P作為頂旋轉,方向為X上升的方向
- 再以X的祖父節點25為頂旋轉,方向為X上升的方向
接下來我們討論上面三種情況是否包含了所有的情況:
- 首先我們假設X有一個兄弟節點S,他是P的另外一個子節點,如果P是黑色的插入X沒有問題(對應情況1),如果P是紅色的那麼他的兩個子節點必須是黑色,所以此時不能單獨存在一個黑色子節點S,否則路徑上的黑色高度就不一樣了,當P為紅色的時候X不可能有兄弟節點。
- 另外一種可能是P的父節點G有一個子節點U,U是P的兄弟節點和X的樹節點,此時如果P是黑色的,插入X不需要進行旋轉。假設P是紅色的,那麼U必須也是紅色的,不然黑色高度就不同了,這種情況在當我們沿路徑向下尋找插入點的時候會變換顏色,會將P和U都變換成黑色節點,所以此時有變換回了情況1。
因此上面討論的三種可能性是全部可能存在的情況(在可能性2和3中X可能是右子節點或者左子節點,以及G可能是右子節點或者左子節點)
Ⅴ、紅-黑樹的刪除
之前我們討論的二叉搜尋樹編寫刪除的代碼比編寫插入的操作的代碼要難很多,紅-黑樹也是如此,刪除節點後要恢複紅黑規則變得很複雜,一般我們會用其他的方法來迴避,比如說只將節點做刪除的標記而不真正的刪除
Ⅵ、紅-黑樹的效率
和一般的二叉搜尋樹類似,紅-黑樹的尋找,插入刪除的時間複雜度為O(log2N),紅-黑樹的尋找時間和普通的二叉搜尋樹尋找的時間幾乎完全一樣,額外的開銷只是儲存空間增加了一個儲存紅黑顏色的空間。
插入和刪除的時間增加了一個常數因子,因為不得不在下行的路徑上和插入點執行顏色變換和旋轉。平均一次插入大概需要一次旋轉,因此插入的時間複雜度還是O(log2N)但是比普通的二叉搜尋樹要慢(不用做顏色變換和旋轉)
大多數應用中尋找的次數比插入和刪除的次數多,所以應用紅-黑樹取代二叉搜尋樹不會增加太多的時間開銷,紅/黑樹狀結構最大的優點就是對有序的資料的操作不會慢到O(N)的時間複雜度。
此篇就是關於紅/黑樹狀結構結構的基本理解,不足之處歡迎指出,不懂得地方歡迎提問。
JAVA資料結構之紅-黑樹