紅黑樹的刪除是在二叉查詢樹的基礎上修改得來的,
從紅黑樹上刪除乙個節點,可以先用普通二叉搜尋樹的方法,將節點從紅黑樹上刪除掉,然後再將被破壞的紅黑性質進行恢復。
我們回憶一下普通二叉樹的節點刪除方法:z指向需要刪除的節點,y指向實質結構上被刪除的結點,如果z節點只有乙個子節點或沒有子節點,那麼y就是指向z指向的節點。如果z節點有兩個子節點,那麼y指向z節點的後繼節點(其實前趨也是一樣的),而z的後繼節點絕對不可能有左子樹。因此,僅從結構來看,二叉樹上實質被刪除的節點最多隻可能有乙個子樹。
偽**如下:
rb-delete(t, z)
if left[z] == nil[t] or right[z] == nil[t]
then y = z //如果z節點只有乙個子節點或沒有子節點,那麼y就是指向z指向的節點。
else y = tree-successor(z) // y指向z節點的後繼節點
if left[y] != nil[t] // y是x的子節點
x = left[y]
else y = right[y]
parent[x] = parent[y] // 直接將x的父節點置為y的父節點,即x的祖先節點
if parent[y] == nil[t] // 根節點為空
then root[t] = x
else if y = left[parent[y]] // y是其父節點的左孩子節點
then left[parent[y]] = x
else right[parent[y]] =x
if y != z
then key[z] = key[y]
if color[y] == black // 如果y是黑色的,則進行修補以保持紅黑樹的性質
rb-delete-fixup(t, x)
return y
如果y是紅色的,刪除後則紅黑性質依然可以得到保持,理由如下:
1,樹中的各節點的黑高度沒有變化,
2,不存在兩個相鄰的紅節點,
3,如果y是紅色的,則不可能是根,根仍然是紅色的。
如果y指向的節點是個黑色節點,那麼就有幾條紅黑性質可能受到破壞了。首先是包含y節點的所有路徑,黑高度都減少了一(第5條被破壞)。其次,如果y的有紅色子節點,y又有紅色的父節點,那麼y被刪除後,就出現了兩個相鄰的紅色節點(第4條被破壞)。最後,如果y指向的是根節點,而y的子節點又是紅色的,那麼y被刪除後,根節點就變成紅色的了(第2條被破壞)。
如果不改變含y路徑的黑高度,那麼樹的其它部分的黑高度就必須做出相應的變化來適應它。所以,我們想辦法恢復原來含y節點的路徑的黑高度。做法就是把y節點的黑色,推到它的子節點x上去。(x可能是nil節點)。這樣,x就可能具有雙重黑色,或是同時具有紅黑兩色,也就是第1條性質被破壞了。
但第1條性質是比較容易恢復的:一、如果x是同時具有紅黑兩色,那麼好辦,直接把x塗成黑色,就行了。而且這樣把所有問題都解決了。因為將x變為黑色,2、4兩條如果有問題的話也會得到恢復。二、如果x是雙黑色,那麼我們希望把這種情況向上推一直推到根節點(調整樹結構和顏色,x的指向新的雙黑色節點,x不斷向上移動),讓根節點具雙黑色,這時,直接把x的一層黑色去掉就行了(因為根節點被包含在所有的路徑上,所以這樣做所有路徑同時黑高減少一,不會破壞紅黑特徵)。
rb-delete-fixup(t, x)
while x != root[t] and color[x] == black
do if x == left[parent[x]] // 分為兩組,兩組是對稱的,分別是x是左子樹或右子樹
then w = right[parent[x]] // w是其兄弟節點
if color[w] == red // w是紅色,case1
then color[w] = black
color[parent[x]] = red
left-rotate(t, parent[x])
w = right[parent[x]]
if color[left[w]] == black and color[right[w]] == black // w是黑色的,兩個孩子都是黑色的case2
then color[w] = red
x = parent[x] // x向上推
else if color[right[w]] = black // w是黑色的,左孩子紅色的,右孩子是黑色的case3
then color[left[w]] = black
color[w] = red
right-rotate(t, w)
w = right[parent[x]]
// case4
color[w] = color[parent[x]]
color[parent[x]] = black
left-rotate(t, parent[x])
x = root[t]
else // x是右子樹,進行類似的操作
same as then clause whith right and left exchanged
color[x] = black
簡單分析下:
情況1:x的兄弟節點w是紅色的
改變w和parent[x]的顏色,再對parent[x]做一次左旋轉,並將w置為x新的兄弟節點,紅黑性質得到保持,轉到情況2,3,4.
情況2:x的兄弟節點w是黑色的,而且w的兩個孩子都是黑色的。
因為w兩個孩子都是黑色的,w也是黑色的,所以從x和w上去掉一重黑色,從而x只有一重黑色,w為紅色,通過x為parent[x]及誒單來重複while迴圈,如果是從情況1進入情況2,新節點x的color為red則結束迴圈。
情況3:x的兄弟節點是黑色的,左孩子是紅色的,右孩子是黑色的。
交換w和左孩子的顏色,並對w進行右旋轉,從而紅黑性質保持一致,這樣情況3轉為情況4。
情況4:x的兄弟節點w是黑色的,w的右孩子是紅色的。
對顏色做修改,並對parent[x]做一次左旋,可以去掉x的額外黑色來把它變成單獨黑色,而不破壞紅黑性質。將x置為根後,while迴圈結束。
資料結構之紅黑樹
定義 紅黑樹是一顆二叉查詢樹,樹中結點顏色或為紅色或為黑色,且滿足如下條件 根結點和所有外結點的顏色為黑色 根結點到任意乙個外結點的路徑上沒有連續的兩個紅色結點,若乙個結點是紅色,則其兩個兒子結點都是黑色 根結點到任意外結點的路徑上都有相同數目的黑色結點。1 插入操作 插入操作可以概括為以下幾個步驟...
《資料結構與演算法》之紅黑樹
二叉查詢樹對於某個節點而言,其左子樹的節點關鍵值都小於該節點關鍵值,右子樹的所有節點關鍵值都大於該節點關鍵值。二叉查詢樹作為一種資料結構,其查詢 插入和刪除操作的時間複雜度都為 o logn 底數為 2。但是我們說這個時間複雜度是在平衡的二叉查詢樹上體現的,也就是如果插入的資料是隨機的,則效率很高,...
資料結構查詢演算法之紅黑樹
紅黑樹對於結點的顏色設定不是任意的,需滿足以下性質的二叉查詢樹才是紅黑樹 紅黑樹中每個結點都有各自的黑高度,整棵樹也有自己的黑高度,即為根結點的黑高度,例如圖 1 中的紅黑樹的黑高度為 3。對於一棵具有 n 個結點的紅黑樹,樹的高度至多為 2lg n 1 所以紅黑樹的時間複雜度為o logn 紅黑樹...