紅黑樹知識點小結
參考資料
使用符號和術語:
N:當前操作的結點
P:當前結點N的父結點
U:當前結點N的叔結點
G:當前結點N的祖父結點,即父結點的父結點
left:當前結點是父結點的左孩子
right:當前結點是父結點的右孩子
A<-B:將B賦值到A修復(restructure/rebalance): 指通過旋轉和結點變色,使插入或刪除結點後的紅黑樹重新滿足基本的5個約束,修復算法只與位置和顏色相關而與結點鍵值大小無關
平衡樹的旋轉
左旋
旋轉鏈的變化形似: \ -> /
右旋
旋轉鏈的變化形似: / -> \
紅黑樹基本約束5點
- 結點
非紅即黑
- 根結點必爲
黑色
- 葉結點NIL必爲
黑色
紅色
結點的子結點必爲黑色
(黑色
結點的子節點可紅可黑
)- 任一結點到其所在分支的各葉結點,每條路徑上的
黑色
結點數目相等
紅黑樹插入
注:該插入算法參考@v_JULY_v的博客,相對wiki較爲簡潔
概要和約束
- 基本插入同AVL樹相似,AVL樹的修復操作是旋轉,但紅黑樹需要旋轉配合變色
- 新插入的結點必爲
紅色
- 插入的結點作爲根結點時,直接變爲
黑色
- 插入結點作爲在
黑色
結點的子結點
時,無須額外的修復操作
插入修復
情況:
- N的P是
紅色
,U是紅色
- N的P是
紅色
,U是黑色
,P和N不同是right
或不同是left
- N的P是
紅色
,U是黑色
,P和N同是right
或同是left
插入修復算法要點:
對 1: P變
黑色
,U變黑色
,G變紅色
,N<-G,再次判斷情況進行修復對 2:若P是
left
,則以N和P爲鏈,左旋
,旋轉後,N <- N的left
(即原本的P),進入情況3;
若P是right
,則以N和P爲鏈,右旋
,旋轉後,N <- N的right
(即原本的P),進入情況3對 3:P變
黑色
,G變紅色
,以P和G爲鏈,若P是left
則右旋
,否則左旋
圖示
注:N爲`left`和N爲`right`的情況均已畫出
紅黑樹刪除
注:該刪除算法參考@Wikipedia,因爲覺得v_July_v寫的有點模糊
概要和約束
1.刪除修復時新增的符號:
D:最初需要被刪除的結點
M:替換用的結點(是D的左子最右結點
或右子最左結點
)
C:M的子節點,若M無子節點,C爲任意一個葉子子節點;若M有1個子節點,則C爲該非葉子的子節點
2.在AVL數中,刪除分三種情況,記被刪除的結點爲 D 的話:
- 1) D無子節點;
- 2) D有1個子節點;
3) D有2個子節點;
分別對應三種重新平衡操作:
- 1)用NULL替換;
- 2)用其唯一的子節點直接替換;
- 3)用D左子的最右結點替換
在紅黑樹中,有子節點特指有非葉子結點,即非空節點
3.出於效率考慮1,第3種情況時,實際上並沒有刪除D,而是用D左子的最右結點的數據覆蓋D的數據,真正被刪除的是D左子的最右結點(不會有右子),這樣就簡化成一個刪除無子節點或只有1個子節點的問題2
刪除操作的實質:M的數據覆蓋D的數據,刪除M,M的位置由C補上,因此D的顏色沒有改變
刪除修復
注:閱讀以下內容前務必閱讀 #概要
情況:
將C標記爲N,以下均以N爲left
討論
M是
紅色
,直接用N補上,結束刪除操作M是
黑色
,用N補上後,分以下6種情況:- N是
紅色
- N是
黑色
且是根節點 - N是
黑色
,S是紅色
,P是黑色
, - N是
黑色
,S是黑色
,S兩子節點均爲黑色
- N是
黑色
,S是黑色
,S右子是黑色
,左子是紅色
- N是
黑色
,S是黑色
,S右子是紅色
,左子顏色任意
- N是
刪除修復算法要點:
- 對1:把N染成
黑色
,直接結束 - 對2:直接結束
- 對3:P變
紅色
,S變黑色
,把問題轉化爲S是黑色
的情況,重新進入算法 - 對4:S變
紅色
,重新進入算法 - 對5:S變
紅色
,S左子變黑色
,以S和S左子爲鏈,右旋
,把問題轉化爲情況4,重新進入算法 - 對6:令S的顏色變爲P的顏色,P變
黑色
,S右子變黑色
,以P和S爲鏈,左旋
,算法結束
圖示
注:下圖只畫出了N爲`left`的情況,N爲`right`的情況參見wiki的代碼
補充
- 葉結點爲NIL,不含數據,僅標記結束
- 紅黑樹並不完全平衡,其確保沒有一條路徑會比其他路徑長出倆倍,因而是接近平衡的
/*
author: lyuavery
date: 07-22-1016
*/
- “Because merely copying a value does not violate any red–black properties, this reduces to the problem of deleting a node with at most one non-leaf child.”
– – wikipedia ↩ - “Once we have solved that problem, the solution applies equally to the case where the node we originally want to delete
has at most one non-leaf child
as to the case just considered where it has two non-leaf children.”
– – wikipedia ↩