Java基礎-理解紅黑樹(刪除)

吾乃上將軍邢道榮發表於2019-03-03
上一篇文章講解了紅黑樹的插入操作  ,這篇講解一下紅黑樹的刪除操作。


在講解紅黑樹刪除之前,先簡單回顧下二叉樹的刪除操作。

Java基礎-理解紅黑樹(刪除)

如果現在有一個二叉樹如上圖所示,我需要刪除66這個節點該怎麼做最快呢?

首先分析一下66這個節點的特點,在66的右邊子樹中,所有的節點都是比66大的。所以要想最快完成刪除操作,只需要在右邊子樹中,找出一個最小的來,替換掉66即可。而真正從樹上被剔除的節點,則是右子樹中最小節點的位置。如圖:

Java基礎-理解紅黑樹(刪除)

同樣的思路,左邊子樹找出一個最大的替換也是可以的。當然如果被刪除的節點本身左右兩個子節點只有一個或者都沒有值的話,那操作就更簡單了,直接剔除即可。

下面開始分析紅黑樹的刪除操作:

紅黑樹刪除操作如下:

  1. 根據二叉樹的刪除操作,找到真正需要從樹上剔除的節點。
  2. 如果需要剔除的節點為黑色,調整紅黑樹的平衡(調整步驟如下)。
那麼調整平衡的時候,可能會遇到幾種情況呢?其實不用說也應該知道,和插入操作的情形一樣,理論上講也是2種情況。

第一種情況,剔除節點(B)的兄弟節點(C)為紅色(左下角為需要剔除的節點):

Java基礎-理解紅黑樹(刪除)

這種情況我們需要做的就是將兄弟節點(C)變為黑色,將父節點(A)變為紅色,對父節點

進行右旋操作。將C的左子節點作為B的兄弟節點。

Java基礎-理解紅黑樹(刪除)

直接刪除B的話,會導致A左右兩邊黑色節點數不一致。造成紅黑樹失去平衡。最好的辦法就是把A的右邊也刪除一個黑色節點。但是因為B的兄弟節點C是紅色,所以不能直接對C進行變色操作。所以只能將AC的顏色互換,然後對A進行右旋操作。將C的左子節點賦給B,作為B的兄弟節點,而因為C是紅節點,紅黑樹不能出現連續兩個紅節點,所以C的子節點必然是黑色。

所以,經過一步調整,在不破換樹平衡的情況下,我們就可以為B找到黑色的兄弟節點了。

接下來的操作遵循情況二即可。

第二種情況,剔除節點(B)的兄弟節點(C)為黑色(左下角為需要剔除的節點):

Java基礎-理解紅黑樹(刪除)

這種情況的話,可以分為兩種子情況討論。

首先,C節點的兩個子節點都為黑色。如果是這種情況的話,操作就更簡單了,直接將C節點變為紅色,然後以剔除節點(B)的父節點A進行迭代判斷即可。此處為什麼要迭代呢?因為從A往下看他的左右兩邊雖然是平衡了,但是兩個子分支都少了一個黑色節點,所以必然會導致樹不平衡。如果A本身是紅色的話,那直接將A改成黑色即可,如果A是黑色的話那就沒辦法了,只能以A為基準向上迭代判斷。

然後如果C節點下面掛有紅色節點該怎麼辦?(C節點不能直接變紅)思路就是如果C節點下面掛有紅色節點,我們應該想辦法把紅色節點挪到左邊去,讓他代替B節點,這樣就可以直接調整到位,不破壞樹的平衡。具體調整步驟如下:

Java基礎-理解紅黑樹(刪除)

將D和A節點設定為黑色,將C節點設定為A原來的顏色,然後對A進行左旋操作即可。

Java基礎-理解紅黑樹(刪除)


所以其實理解一下的話,紅黑樹還是很簡單的。


相關文章