Java基礎-理解紅黑樹(插入)

     周圍有一些朋友總說:「面試時候看到紅黑樹真的頭大!各類狀況太難記了。」確實,若是僅僅想經過記憶來搞定紅黑樹那確實有點難度的,可是若是理解的話,紅黑樹其實很簡單,因此我就分享一下我對紅黑樹的理解。面試

1.簡單複習下紅黑樹的規則。

  1. 節點必須是紅色或者黑色。
  2. 根節點必須是黑色。
  3. 葉節點(NIL)是黑色的。(NIL節點無數據,是空節點)
  4. 不能出現連續兩個紅色節點。
  5. 從任一節點出發到其每一個葉子節點的路徑,黑色節點的數量是相等的。

2.先講解一波操做,後面再給出論證

插入操做以下,post

  1. 每次插入第一步,將新插入節點設置爲紅色。
  2. 每次插入最後一步,將根節點設置爲黑色。
  3. 當且僅當新插入節點的父節點爲紅色時,從新調整紅黑樹的平衡(調整步驟以下)。
根據插入操做3,只有新插入節點父節點爲紅色時,才須要調節紅黑樹,那麼父節點爲紅色時會有幾種狀況呢?理論上講只有兩種。

第一種:新插入節點 父節點的 兄弟節點 爲黑色(左下角節點爲新插入節點)3d


第二種:新插入節點 父節點的 兄弟節點 爲紅色(左下角節點爲新插入節點)cdn


兩種狀況逐個分析。blog

第一種狀況下,想要恢復樹的平衡,只須要將連續的兩個紅色節點,分一個給另一個分支便可。這樣的話,若是原來的樹是平衡的,新樹也必然平衡(兩個分支的黑色節點數量並未變化)。get


固然說是一回事,作是另外一回事。下面就看看實際狀況下,如何操做。it



原樹已經有12,10 ,13三個元素,新插入了一個8節點,此時,8與其父節點10都爲紅色,須要調整。將10設置爲黑色,將12設置爲紅色,而後對節點12進行左旋操做(其實就是把8,10,12這三個順序節點,從新以中間值10爲中心在排一下)。io


若是新插入的節點是11那該怎麼辦呢。class


此時須要重排的三個節點爲12,10,11,可是中間值11在最下面,直接重排不方便。因此須要多一步操做,對10節點進行右旋操做。lazyload


這樣12 ,11 ,10 這三個節點也是順序排列了。下一步操做就同上。若是從右邊插入的話,操做也同樣,鏡像一下就ok。

如今再分析第二種狀況(左下角爲新插入節點)。


這種狀況處理起來更簡單,只須要將新插入節點的父節點,以及父節點的兄弟節點一塊兒變成黑色,而後將爺爺節點變紅便可(兩個分支的黑色節點數量依然沒有變化)。


由於從爺爺節點往下,每一個分支原來是一個黑色節點,如今依然是一個黑色節點,因此樹仍是平衡的,可是須要注意的是,由於爺爺節點由黑變紅了。因此還得以爺爺節點爲基準,迭代向上判斷。直到爺爺節點的父節點爲黑色或者爺爺節點爲根節點爲止。至於迭代中可能的狀況,也無非就是咱們列出來的這兩種,參照一下便可。

3.最後論證插入操做的合理性:

紅黑樹規則:

  1. 節點必須是紅色或者黑色。
  2. 根節點必須是黑色。
  3. 葉節點(NIL)是黑色的。(NIL節點無數據,是空節點)
  4. 不能出現連續兩個紅色節點。
  5. 從任一節點出發到其每一個葉子節點的路徑,黑色節點的數量是相等的。
插入操做
  1. 每次插入第一步,將新插入節點設置爲紅色。
  2. 每次插入最後一步,將根節點設置爲黑色。
  3. 當且僅當新插入節點的父節點爲紅色時,從新調整紅黑樹的平衡


首先,每次插入的第一步將插入節點設置爲紅色,由於若是樹本來是平衡的話,插入一個紅色節點並不會影響到規則5(從任一節點出發到其每一個葉子節點的路徑,黑色節點的數量是相等的)。

其次,在插入最後一步將根節點設置爲黑色,這樣規則2(根節點必須是黑色)就永遠知足。

最後依據插入操做3(當且僅當新插入節點的父節點爲紅色時,從新調整紅黑樹的平衡),以及調整步驟,每次調整事後,均可以保證規則4(不能出現連續兩個紅色節點)也是能夠知足的。

這樣一來,只要嚴格遵循插入的這3條操做,就能夠嚴格的保證紅黑樹的平衡了。或許你會問剛開始的第一條論證有一個前提條件「樹本來是平衡的話」,若是這個前提條件不知足怎麼辦?

其實當你插入第一個根節點時,樹已經處於了平衡的狀態。因此只要一開始就遵循插入操做,根本就不會存在樹不平衡的狀況。因此這個插入操做是合理的。

下一篇:紅黑樹的刪除操做

相關文章
相關標籤/搜索