紅黑樹刪除操作

節(jié)點標識

待刪除節(jié)點D
兄弟節(jié)點B
侄子節(jié)點C
父親節(jié)點P
雙黑節(jié)點N

刪除步驟

首先分為三類:

  • D有2個非空子節(jié)點
    • 找到D的后續(xù)節(jié)點back较沪,將back的值傳遞給D侨核,此時待刪除節(jié)點變?yōu)? back,而此時的back一定只有一個外部子節(jié)點乙帮,因此轉(zhuǎn)為第三類
// 待刪除節(jié)點有2個外部子節(jié)點
    if (n.left != null && n.right != null) {
        // 后繼節(jié)點
        RBNode<T> back = successor(n);
        n.data = back.data;
        delete(back);
        return;
    }
  • D沒有非空子節(jié)點
    • 判斷當前節(jié)點是否為根節(jié)點root,若是,則直接root = null捧搞。否則,直接刪除該節(jié)點狮荔,判斷該節(jié)點為黑胎撇,則出現(xiàn)雙黑節(jié)點N,需要進行雙黑節(jié)點處理fixAfterDelete()
// 待刪除節(jié)點沒有外部子節(jié)點
    else if (n.left == null && n.right == null) {
        if (isLeft(n))
            p.left = null;
        else if (isRight(n))
            p.right = null;
        else {// 說明待刪除的節(jié)點子節(jié)點為null殖氏,且父節(jié)點為null晚树,此時樹中僅剩根節(jié)點
            root = null;
            return;
        }
    }
       ...
       if (!isRed(n))
        fixAfterDelete(n,p);
  • D只有1個非空子節(jié)點
    • 若D為根節(jié)點root,直接將非空子節(jié)點稱為根節(jié)點root受葛,并將節(jié)點顏色修正為黑色题涨,算法結(jié)束
// n為根節(jié)點
    else {
        root = n.left == null?n.right:n.left;
        root.parent = null;
        root.color = BLACK;
        return;
    }
  • 若D為紅色,直接刪除总滩,算法結(jié)束纲堵。若D為黑色,且有一個紅色子節(jié)點闰渔,則將子節(jié)點取代D的位置席函,并將顏色修正為黑色,結(jié)束算法
  • 出現(xiàn)雙黑節(jié)點冈涧,需要進行雙黑節(jié)點處理fixAfterDelete()

雙黑節(jié)點處理

分為三類:

  • 雙黑節(jié)點N的兄弟節(jié)點B為紅色
    • 交換N.parentB的顏色茂附。B為,則B左旋督弓;B為营曼,則B右旋。該變換后愚隧,轉(zhuǎn)為第二類情況
// 兄弟節(jié)點為紅色蒂阱,先做顏色變換和旋轉(zhuǎn)操作
    if (isRed(brother)) {
        // 父節(jié)點與兄弟交換顏色
        boolean temp = p.color;
        p.color = brother.color;
        brother.color = temp;
        // 兄弟在右,則左旋狂塘;反之
        if (isRight(brother))
            left_rotate(p);
        else
            right_rotate(p);
        // 得到新的兄弟節(jié)點
        brother = p.left == null?p.right:p.left;
    }
  • 雙黑節(jié)點N的兄弟節(jié)點B為黑色
    • B存在紅色子節(jié)點C
      (1). B和C都是左子節(jié)點/右子節(jié)點(遠侄子):B.color = N.parent.color录煤、C.color = BLACKN.parent.color = BLACK荞胡,對N.parent左旋/右旋
      (2). B為/妈踊、C為/(近侄子):B先作右旋/左旋,轉(zhuǎn)為情況1
// 兄弟節(jié)點存在紅色子節(jié)點
        if (isRed(brother.left) || isRed(brother.right)) {
            // 紅色子節(jié)點
            RBNode<T> redC = isRed(brother.left)?brother.left:brother.right;
            fixWhenBrotherHasRed(p,brother,redC);
        }
// 當兄弟節(jié)點存在紅色子節(jié)點的情況下進行調(diào)整
    // 輸入?yún)?shù):父節(jié)點泪漂、兄弟節(jié)點廊营、紅色子節(jié)點
    private void fixWhenBrotherHasRed(RBNode<T> p, RBNode<T> b, RBNode<T> c) {
        if (isRight(b) && isLeft(c)) {
            right_rotate(b);
            // 近侄子和兄弟互換歪泳,變?yōu)檫h侄子情況
            RBNode<T> temp;
            temp = c;
            c = b;
            b = temp;
        }
        if (isLeft(b) && isRight(c)) {
            left_rotate(b);
            // 近侄子和兄弟互換,變?yōu)檫h侄子情況
            RBNode<T> temp;
            temp = c;
            c = b;
            b = temp;
        }
        b.color = p.color;
        p.color = BLACK;
        c.color = BLACK;
        if (isRight(b))
            left_rotate(p);
        else
            right_rotate(p);
    }
* B有兩個黑色子節(jié)點(包括`NIL節(jié)點`)

作以下調(diào)整:B.color = RED赘风,N.parent.color = BLACK夹囚。若N.parent.color原來為紅色,則算法結(jié)束邀窃。否則荸哟,將N.parent作為新的雙黑節(jié)點,繼續(xù)fixAfterDelete()

//兄弟節(jié)點存在2個黑色子節(jié)點瞬捕,包含NIL節(jié)點
    else {
        brother.color = RED;
        if (isRed(p)) {
            p.color = BLACK;
        }else {
            // 若父節(jié)點原來為black鞍历,則父節(jié)點作為新的雙黑節(jié)點繼續(xù)調(diào)整,直到根節(jié)點
            if (p.parent != null)
                fixAfterDelete(p,p.parent);
        }
    }

后續(xù)傳圖

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末肪虎,一起剝皮案震驚了整個濱河市劣砍,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌扇救,老刑警劉巖刑枝,帶你破解...
    沈念sama閱讀 216,544評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異迅腔,居然都是意外死亡装畅,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評論 3 392
  • 文/潘曉璐 我一進店門沧烈,熙熙樓的掌柜王于貴愁眉苦臉地迎上來掠兄,“玉大人,你說我怎么就攤上這事锌雀÷煜Γ” “怎么了?”我有些...
    開封第一講書人閱讀 162,764評論 0 353
  • 文/不壞的土叔 我叫張陵腋逆,是天一觀的道長婿牍。 經(jīng)常有香客問我,道長惩歉,這世上最難降的妖魔是什么等脂? 我笑而不...
    開封第一講書人閱讀 58,193評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮柬泽,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘嫁蛇。我一直安慰自己锨并,他們只是感情好,可當我...
    茶點故事閱讀 67,216評論 6 388
  • 文/花漫 我一把揭開白布睬棚。 她就那樣靜靜地躺著第煮,像睡著了一般解幼。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上包警,一...
    開封第一講書人閱讀 51,182評論 1 299
  • 那天撵摆,我揣著相機與錄音,去河邊找鬼害晦。 笑死特铝,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的壹瘟。 我是一名探鬼主播鲫剿,決...
    沈念sama閱讀 40,063評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼稻轨!你這毒婦竟也來了灵莲?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,917評論 0 274
  • 序言:老撾萬榮一對情侶失蹤殴俱,失蹤者是張志新(化名)和其女友劉穎政冻,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體线欲,經(jīng)...
    沈念sama閱讀 45,329評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡明场,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,543評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了询筏。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片榕堰。...
    茶點故事閱讀 39,722評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖嫌套,靈堂內(nèi)的尸體忽然破棺而出逆屡,到底是詐尸還是另有隱情,我是刑警寧澤踱讨,帶...
    沈念sama閱讀 35,425評論 5 343
  • 正文 年R本政府宣布魏蔗,位于F島的核電站,受9級特大地震影響痹筛,放射性物質(zhì)發(fā)生泄漏莺治。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,019評論 3 326
  • 文/蒙蒙 一帚稠、第九天 我趴在偏房一處隱蔽的房頂上張望谣旁。 院中可真熱鬧,春花似錦滋早、人聲如沸榄审。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽搁进。三九已至浪感,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間饼问,已是汗流浹背影兽。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留莱革,地道東北人峻堰。 一個月前我還...
    沈念sama閱讀 47,729評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像驮吱,于是被迫代替她去往敵國和親茧妒。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,614評論 2 353

推薦閱讀更多精彩內(nèi)容