紅黑樹核心程式碼分析(JAVA)
紅黑色的五條性質
(1)每個節點或者是黑色,或者是紅色。
(2)根節點是黑色。
(3)每個葉子節點(NIL)是黑色。 [注意:這裡葉子節點,是指為空(NIL或NULL)的葉子節點!]
(4)如果一個節點是紅色的,則它的子節點必須是黑色的。
(5)從一個節點到該節點的子孫節點的所有路徑上包含相同數目的黑節點。
刪除之後的處理(removeAfter()方法的實現)
對於紅黑樹的刪除:因為對於度為二的節點最終都會轉化為刪除度為一或者刪除度為0的節點
分為兩種:
1.刪除紅色節點
對於刪除紅色節點的情況,因為刪除紅色節點不會影響紅黑樹的性質,因此刪除紅色節點不需要處理,直接刪除即可
//程式碼體現
if(isRed(node)){return;} //紅色葉子節點(一種)
2.刪除黑色節點
- 對於刪除黑色節點的情況分為三種情況:
- 擁有兩個 RED 子節點的 BLACK 節點,不可能被直接刪除,因為會找到它的子節點替代刪除【即都會轉化為下面兩種情況的判斷】,因此不需要考慮這樣的情況
- 刪除擁有一個 RED 子節點的BLACK 節點 【情況一】
- 刪除BLACK 葉子節點 【情況二】
對於上面只需要考慮兩種情況
情況一:擁有一個 RED 子節點的BLACK 節點的刪除
對於擁有一個red紅色子節點的黑色節點的刪除而言,只需要將替代被刪黑色節點的紅色的子節點染黑即可,這樣就能保證紅黑樹的第五條性質。
例如:
上圖表示刪除 60 這個黑色節點,即將78指向60的線指向60的子節點,再將47這個節點染黑,如下所示:
情況二:刪除的是BLACK 葉子節點
刪除BLACK葉子節點分為兩種情況,第一種情況為刪除根節點(根節點為黑色),直接刪除即可,不做任何處理,root = null。
第二種情況為刪除的不是根節點,即又分為兩種情況:
1.被刪除的節點的兄弟節點為黑色
2.被刪除的節點的兄弟節點為紅色 (且可以根據紅黑樹的性質得:該紅節點必定有黑色的子節點,這裡是為後面處理該情況埋下伏筆)
【補充:對於上面兩種情況,可能有人會問:存在沒有兄弟的情況嗎?答案是不可能,除非是 root 節點,上面已經考慮了。為什麼呢?因為這是根據紅黑樹的性質決定,比如第五條性質中:從一個節點到該節點的子孫節點的所有路徑上包含相同數目的黑節點。】
對於上面的兄弟節點為黑色的情況又分為兩種情況:一種是被刪除的兄弟節點有至少一個紅色子節點,一種是沒有紅色子節點(也可以是說沒有子節點)
一:對於被刪除的兄弟節點有至少一個紅色子節點的情況
- 解決方案為:
- 對被刪之後的情況進行旋轉【分為LL/LR/RL/RR】
- 旋轉之後的中心節點繼承 被刪節點的 parent 的顏色
- 旋轉之後的左右節點染成BLACK
例:刪除91 【這裡可以看出節點 91 刪完後 50 -44 -41為LL情況,對父節點:50進行右旋轉即可】
刪後 如下所示: 【註解:中心44繼承繼承 被刪節點的 parent 的顏色:BLACK,旋轉之後的左右節點染成BLACK】
二:對於被刪除的兄弟節點是黑色且該黑色兄弟節點也沒有紅色子節點的情況
- 分為兩種情況
- 1.被刪除節點的父節點為紅色的情況
- 2.被刪除節點的父節點為黑色的情況
對於被刪除節點的父節點為紅色的情況
- 解決方案
- 1.父節點染黑----> black(parent);
- 2.黑兄弟染紅-----> red(sibling);
如下圖所示刪除95 【 black(parent); red(sibling); 】
刪除95後
對於被刪除節點的父節點為黑色的情況 【會導致parent 下溢】
- 解決方案
- 1.和上面一樣操作
- 2.因為導致parent下溢,這時只需要將 parent 當成被刪除的節點處理即可【遞迴呼叫】
被刪除的節點的兄弟節點為紅色
- 解決方案
- 兄弟節點染成BLACK,parent 染成 RED ,進行旋轉
- 於是又回到兄弟節點為BLACK的情況
對於上面的情況,刪除86這個節點,該節點的兄弟節點為 10 紅色節點,假如我們可以讓 86 的父節點 81 的左left 指向31,這樣我們就回到了上面 86 兄弟節點為黑色的情況!【妙啊~~~】
如何實現呢?
我們想到了旋轉!,對81這個父節點右旋轉,即可讓81的左孩子指標指向 31 這個節點,其他情況以此類推~
removeAfter()完整程式碼:
public void removeAfter(Red_Node node,Red_Node replacement){
if(isRed(node)){return;} //紅色葉子節點(一種)
if(isRed(replacement)){ //度為一的節點(兩種)
black(replacement);
return;
}
/*** “ 刪除黑色的情況 ”
* 最後一種情況:度為 " 一 " 且 被刪除的節點顏色為黑色的情況
* 看被刪除的節點的兄弟節點的顏色判斷進行是否可以借用或者進行下溢
* sibling : 兄弟節點
* 當黑色的節點存在時,必定在同階的高度中有節點,即:----> 黑節點一定存在兄弟節點
*/
Red_Node parent = node.parent;
if(parent == null){
return; //刪除的是根節點【度為一且為黑】,也是遞迴出口!!!
}
boolean left = parent.left ==null;
Red_Node sibling = left ? parent.right:parent.left;
/**
* 因為旋轉的方向不同,分為被刪除的節點的位置不一樣,在右邊和左邊的情況
*/
if(left){ //被刪除的節點在左邊,兄弟節點在右邊
if(isRed(sibling)){
red(parent);
black(sibling);
while_left(parent);
sibling = parent.right;
}
//兄弟節點必定是黑色的
if(isBlack(sibling.left) && isBlack(sibling.right)){ //兄弟節點的左右節點都是黑色!且當子節點是null時預設為黑色
boolean parentBlack = isBlack(parent);
black(parent);
red(sibling);
if(parentBlack){
removeAfter(parent,null);
}
}else { //兄弟節點中至少有一個子節點為紅色【即可以被node節點借!!】
if(isBlack(sibling.right)){
while_right(sibling);
sibling = parent.right;
}
color(sibling,colorOf(parent));
black(sibling.right);
black(parent);
while_left(parent);
}
}else { //被刪除的節點在右邊,兄弟節點在左邊
/**
* 先處理兄弟是紅色的情況 --- > 轉為黑色情況
* 後面直接處理黑色情況即可
*/
if(isRed(sibling)){
red(parent);
black(sibling);
while_right(parent);
sibling = parent.left;
}
//兄弟節點必定是黑色的
if(isBlack(sibling.left) && isBlack(sibling.right)){ //兄弟節點的左右節點都是黑色!且當子節點是null時預設為黑色
boolean parentBlack = isBlack(parent);
black(parent);
red(sibling);
if(parentBlack){
removeAfter(parent,null);
}
}else { //兄弟節點中至少有一個子節點為紅色【即可以被node節點借!!】
if(isBlack(sibling.left)){
while_left(sibling);
sibling = parent.left;
}
color(sibling,colorOf(parent));
black(sibling.left);
black(parent);
while_right(parent);
}
}
}
待續……
紅黑樹完整程式碼:https://blog.csdn.net/m0_46542703/article/details/110354479
相關文章
- Java集合原始碼分析之基礎(六):紅黑樹(RB Tree)Java原始碼
- 死磕 java集合之TreeMap原始碼分析(四)——紅黑樹全解析Java原始碼
- 死磕 java集合之TreeMap原始碼分析(二)——紅黑樹全解析Java原始碼
- 死磕 java集合之TreeMap原始碼分析(三)——紅黑樹全解析Java原始碼
- 死磕 java集合之TreeMap原始碼分析(一)——紅黑樹全解析Java原始碼
- Linux核心資料管理利器--紅黑樹Linux
- 紅黑樹
- 死磕 java集合之TreeMap原始碼分析(二)- 內含紅黑樹分析全過程Java原始碼
- 死磕 java集合之TreeMap原始碼分析(三)- 內含紅黑樹分析全過程Java原始碼
- 死磕 java集合之TreeMap原始碼分析(一)- 內含紅黑樹分析全過程Java原始碼
- 演算法導論學習--紅黑樹詳解之刪除(含完整紅黑樹程式碼)演算法
- Java基礎-理解紅黑樹(插入)Java
- Java實現紅黑樹(平衡二叉樹)Java二叉樹
- Java原始碼閱讀之TreeMap(紅黑樹) - JDK1.8Java原始碼JDK
- Java基礎-理解紅黑樹(刪除)Java
- Java HashMap原始碼分析(含雜湊表、紅黑樹、擾動函式等重點問題分析)JavaHashMap原始碼函式
- 徹底理解紅黑樹及JavaJDK1.8TreeMap原始碼分析JavaJDK原始碼
- 瞭解紅黑樹的起源,理解紅黑樹的本質
- 紅黑樹左右旋
- 淺談紅黑樹
- 紅黑樹詳解
- 從紅黑樹的本質出發,徹底理解紅黑樹!
- Java集合(3)一 紅黑樹、TreeMap與TreeSet(上)Java
- Java集合(4)一 紅黑樹、TreeMap與TreeSet(下)Java
- 【一份程式碼搞定資料結構】紅黑樹(更新中)資料結構
- js實現紅黑樹JS
- 什麼是紅黑樹
- 紅黑樹新增刪除
- 二、JAVA知識點之HashMap、TreeMap、紅黑樹——精髓JavaHashMap
- 2-3-4樹對應紅黑樹的實現,紅黑樹的融會貫通!!!
- 用Js實現紅黑樹JS
- 資料結構--紅黑樹資料結構
- 平衡二叉查詢樹:紅黑樹
- 資料結構之「紅黑樹」資料結構
- 紅黑樹其實很簡單
- ava 集合 | 紅黑樹 | 前置知識
- 紅黑樹的原理以及實現
- 頂尖Java工程師的紅黑技能樹,如何快速點亮?Java工程師