原文**:
組內培訓,講紅黑樹,找出演算法導論,啃了乙個週末,其中插入結點很簡單,刪除結點有點複雜,但跟著演算法導論上一步一步來沒有什麼問題。不想備份blog的,所以沒有把上穿。可直接察看ppt。
紅黑樹性質
1.每個節點或是紅的,或是黑的
2.根節點是黑的
3.每個葉結點(nil)都是黑的
4.如果乙個結點是紅的,則它的兩個兒子都是黑的
5.對每個結點,從該節點到其子孫結點的所有路徑上包含相同數目的黑結點
*從某個結點x出發(不包括該結點)到達乙個葉結點的任意一條路徑上,黑色結點的個數成為該結點x的黑高度,用bh(x)表示。
*引理:一顆有n個內節點的紅黑樹的高度之多為2lg(n+1)
插入不變式
a)結點z是紅色。
b)如果p[z]是根,則p[z]是黑色。
c)如果有紅黑樹的性質被破壞,則至多只有乙個被破壞,並且不是性質2)就是性質4)。如果違反性質2),則發生的原因是z是根而且是紅的。如果違反性質4),則原因是z和p[z]都是紅色的,則p[p[z]]必然是黑色的。
針對違反性質4)
①z的叔叔y是紅色的
②z的叔叔y是黑色的,而且z是右孩子
③z的叔叔y是黑色的,而且z是左孩子
z的叔叔y是黑色的。這兩種情況是通過z是p[z]的左孩子還是右孩子來區別。在情況2中,結點z是他的父親的右孩子。我們立即使用乙個左旋來將此情況轉變為情況3,此時結點z成為左孩子。因為z和p[z]都是紅色的,所以所做的旋轉對結點的黑高度和性質5)都無影響。在情況3中,要改變某些結點的顏色,並作一次右旋以保持性質5。這樣,由於在一行中不在有兩個連續的紅色結點,因而,所有的處理完畢,無需再次執行while迴圈。
二叉查詢樹刪除
*二叉查詢樹刪除(刪除結點z)
如果z沒有子女,則修改其父結點p[z],使nil為其子女;
如果結點z只有乙個子女,則可以通過在其子結點與父結點間建立一條鏈來刪除z;
如果結點z有兩個子女,先刪除z的後繼y,再用y的內容替代z的內容。
*後繼二叉樹中,如果所有的關鍵字均不相同,則某一結點x的後繼既具有大於key[x]中的關鍵字中最小者的那個結點。
紅黑樹刪除
rb-delete(t,z)
1 if left[z] = nil[t] or right[z] = nil[t]
2 then y ← z
3 else y ← tree-successor(z)
4 if left[y] ≠ nil[t]
5 then x ← left[y]
6 else x ← right[y]
7 p[x] ← p[y]
8 if p[y] = nil[t]
9 then root[t] ← x
10 else if y = left[p[y]]
11 then left[p[y]] ← x
12 else right[p[y]] ← x
13 if y ≠ z
14 then key[z] ← key[y]
15 copy y』s satellite data into z
16 if color[y] = black
17 then rb-delete-fixup(t, x)
18 return y
a.如果被刪除的結點是紅色的,則當結點被刪除後,紅黑性質仍然得以保持,理由如下:
a)樹中各結點的黑高度都沒有變化
b)不存在兩個相鄰的紅色結點
c)因為如果該節點是紅的,就不可能是根,所以跟仍然是黑色的
b.如果被刪除的結點是黑色的,則會產生三個問題。
要刪除的結點y,如果y有個不是nil的孩子,則x為y的唯一孩子;如果y沒有孩子,則x為nil,把x的父節點(原來是y)賦值為y的父節點
①如果y原來是根結點,而y的乙個紅色的孩子成為了新的根,這就違反了性質2)。
②如果x和p[y](現在也是p[x])都是紅的,就違反了性質4)。
③刪除y將導致先前包含y的任何路徑上黑結點個數少1。因此,性質5)被y的乙個祖先破壞了。補救這個問題的乙個辦法就是把結點x視為還有額外的一重黑色。也就是說,如果將任意包含結點x的路徑上黑結點的個數加1,則這種假設下,性質5)成立。當將黑節點y刪除時,將其黑色「下推」至其子節點。現在問題就變為結點x可能既不是紅,也不是黑,從而違反了性質1)。結點x是雙重黑色或紅黑,這就分別給包含x的路徑上黑結點的貢獻2個或1個。x的color屬性仍然是red(如果x是紅黑的)或者black(如果x是雙重黑色)。換言之,乙個結點額外的黑色反映在x指向它,而不是他的color屬性。
刪除演算法
rb-delete-fixup(t, x)
1 while x ≠ root[t] and color[x] = black
2 do if x = left[p[x]]
3 then w ← right[p[x]]
4 if color[w] = red
5 then color[w] ← black case1
6 color[p[x]] = red case1
7 left-rotate(t,p[x]) case1
8 w ← right[p[x]] case1
9 if color[right[w]] = black and color[right[w]= black
10 then color[w] ← red case2
11 x ← p[x] case2
12 else if color[right[w]] = black
13 then color[left[w]] ← black case3
14 color[w] ← red case3
15 right-rotate(t,w) case3
16 w ← right[p[x]] case3
17 color[w] ← color[p[x]] case4
18 color[p[x]] ← black case4
19 color[right[w]] ← black case4
20 left-rotate(t,p[x]) case4
21 x ← root[t] case4
22 else (same as then clause with 「right」 and 「left」 exchanged)
23 color[x] ← black
第1-22行中while迴圈的目的是將額外的黑色沿樹上移,直到:
1.x指向乙個紅黑結點,將x(單獨)著為黑色。
2.x指向根,這時可以簡單地消除那個額外的黑色,或者
3.作必要的旋轉和顏色修改
紅黑樹(演算法導論)
測試 所用的例子為算導第三版p179圖13 4 include using namespace std const bool black 0 黑色 const bool red 1 紅色 struct node 結點結構 class rb tree 初始化nil結點和root node left r...
演算法導論例程 紅黑樹
紅黑樹是比較重要的資料結構,作為乙個典型的平衡二叉樹 沒有一條簡單路徑是其他路徑的二倍 它與二叉搜尋樹的區別是它的結點多了乙個屬性 color,color有兩種值,red和black,顏色的選取遵循以下原則 1 每個節點是紅色的,或是黑色的 2 根節點是黑色的 鬆弛紅黑樹 relaxed red b...
演算法導論學習筆記 紅黑樹
紅黑樹的5個性質 1 每個結點要麼是紅的,要麼是黑的。2 根結點是黑的。3 每個葉結點,即空結點 nil 是黑的。4 如果乙個結點是紅的,那麼它的倆個兒子都是黑的。5 對每個結點,從該結點到其子孫結點的所有路徑上包含相同數目的黑結點。public class rbtree 當在某個結點nodex上,...