紅黑樹其實並不難,只是你還沒看過ta

紅黑樹概念

R-B Tree,全稱是Red-Black Tree,又稱爲“紅黑樹”,它一種特殊的二叉查找樹。紅黑樹的每個節點上都有存儲位表示節點的顏色,可以是紅(Red)或黑(Black)。

紅黑樹的特性

(1)每個節點或者是黑色,或者是紅色。

(2)根節點是黑色。

(3)每個葉子節點(NIL)是黑色。 [注意:這裏葉子節點,是指爲空(NIL或NULL)的葉子節點!]

(4)如果一個節點是紅色的,則它的子節點必須是黑色的。

(5)從一個節點到該節點的子孫節點的所有路徑上包含相同數目的黑節點。

紅黑樹左旋

對x進行左旋,意味着,將“x的右孩子”設爲“x的父親節點”;即,將 x變成了一個左節點(x成了爲z的左孩子)!。 因此,左旋中的“左”,意味着“被旋轉的節點將變成一個左節點”。


f926b9529ad84220b69cb6234e5c0184


LEFT-ROTATE(T, x)

y ← right[x] // 前提:這裏假設x的右孩子爲y。下面開始正式操作

right[x] ← left[y] // 將 “y的左孩子” 設爲 “x的右孩子”,即 將β設爲x的右孩子

p[left[y]] ← x // 將 “x” 設爲 “y的左孩子的父親”,即 將β的父親設爲x

p[y] ← p[x] // 將 “x的父親” 設爲 “y的父親”

if p[x] = nil[T]

then root[T] ← y // 情況1:如果 “x的父親” 是空節點,則將y設爲根節點

else if x = left[p[x]]

then left[p[x]] ← y // 情況2:如果 x是它父節點的左孩子,則將y設爲“x的父節點的左孩子”

else right[p[x]] ← y // 情況3:(x是它父節點的右孩子) 將y設爲“x的父節點的右孩子”

left[y] ← x // 將 “x” 設爲 “y的左孩子”

p[x] ← y // 將 “x的父節點” 設爲 “y”


7fd78abd7ba5410095969c56e8962046


紅黑樹右旋

對x進行右旋,意味着,將“x的左孩子”設爲“x的父親節點”;即,將 x變成了一個右節點(x成了爲y的右孩子)! 因此,右旋中的“右”,意味着“被旋轉的節點將變成一個右節點”。


8a2e37709a7349a8972e7e4cb439200e


RIGHT-ROTATE(T, y)

x ← left[y] // 前提:這裏假設y的左孩子爲x。下面開始正式操作

left[y] ← right[x] // 將 “x的右孩子” 設爲 “y的左孩子”,即 將β設爲y的左孩子

p[right[x]] ← y // 將 “y” 設爲 “x的右孩子的父親”,即 將β的父親設爲y

p[x] ← p[y] // 將 “y的父親” 設爲 “x的父親”

if p[y] = nil[T]

then root[T] ← x // 情況1:如果 “y的父親” 是空節點,則將x設爲根節點

else if y = right[p[y]]

then right[p[y]] ← x // 情況2:如果 y是它父節點的右孩子,則將x設爲“y的父節點的左孩子”

else left[p[y]] ← x // 情況3:(y是它父節點的左孩子) 將x設爲“y的父節點的左孩子”

right[x] ← y // 將 “y” 設爲 “x的右孩子”

p[y] ← x // 將 “y的父節點” 設爲 “x”

添加操作

第一步: 將紅黑樹當作一顆二叉查找樹,將節點插入。

第二步:將插入的節點着色爲"紅色"。

根據被插入節點的父節點的情況,可以將"當節點z被着色爲紅色節點,並插入二叉樹"劃分爲三種情況來處理。

① 情況說明:被插入的節點是根節點。

處理方法:直接把此節點塗爲黑色。

② 情況說明:被插入的節點的父節點是黑色。

處理方法:什麼也不需要做。節點被插入後,仍然是紅黑樹。

③ 情況說明:被插入的節點的父節點是紅色。這種情況下,被插入節點是一定存在非空祖父節點的;進一步的講,被插入節點也一定存在叔叔節點(即使叔叔節點爲空,我們也視之爲存在,空節點本身就是黑色節點)。理解這點之後,我們依據"叔叔節點的情況",將這種情況進一步劃分爲3種情況(Case)。


1f101316ff25453b9283ef1e61207b2b



第三步: 通過一系列的旋轉或着色等操作,使之重新成爲一顆紅黑樹。

刪除操作

第一步:將紅黑樹當作一顆二叉查找樹,將節點刪除。

這和"刪除常規二叉查找樹中刪除節點的方法是一樣的"。分3種情況:

① 被刪除節點沒有兒子,即爲葉節點。那麼,直接將該節點刪除就OK了。

② 被刪除節點只有一個兒子。那麼,直接刪除該節點,並用該節點的唯一子節點頂替它的位置。

③ 被刪除節點有兩個兒子。那麼,先找出它的後繼節點;然後把“它的後繼節點的內容”複製給“該節點的內容”;之後,刪除“它的後繼節點”。

第二步:通過"旋轉和重新着色"等一系列來修正該樹,使之重新成爲一棵紅黑樹。

因爲"第一步"中刪除節點之後,可能會違背紅黑樹的特性。所以需要通過"旋轉和重新着色"來修正該樹,使之重新成爲一棵紅黑樹。

選擇重着色3種情況。

① 情況說明:x是“紅+黑”節點。

處理方法:直接把x設爲黑色,結束。此時紅黑樹性質全部恢復。

② 情況說明:x是“黑+黑”節點,且x是根。

處理方法:什麼都不做,結束。此時紅黑樹性質全部恢復。

③ 情況說明:x是“黑+黑”節點,且x不是根。

處理方法:這種情況又可以劃分爲4種子情況。這4種子情況如下表所示:


00d5a39ff7444403b226d5c1a71aa5a8


紅黑色的大體思想就是上面描述的那樣,裏面還有很多情況要考慮,本文只是簡單的講述思想,大家有興趣的可以深入研究一下,謝謝大家的支持!


196c801cfae84f5994256b01cf9db93b


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章