整理筆記[紅黑樹]

紅黑樹的其實就是加了操作的AVL樹,這一類的樹形結構戒幔,主要區(qū)別就是調整維護吠谢,刪除維護的策略不同。

因為紅黑樹的情況是高度對稱的诗茎,那么所有的情況都能壓縮一半工坊。

插入操作

插入簡單,主要難點在于插入操作的維護敢订,插入操作需要維護的是什么呢王污?
站在插入點的祖父點看,插入點和插入點的父親都是紅色枢析,這個時候就需要盤它玉掸。

插入情況

你插入點在4,5醒叁,6司浪,7泊业。并且他爹是紅色(8種情況)。那就盤(tiao)它(zheng)啊易。
如果他爹是黑色吁伺,黑點下插紅點,滿足條件租谈,不調篮奄。

插入與插入調整操作
RBTNode *insert_maintain(RBTNode *root) {//插入策略
    if (!has_red_child(root)) return root;
    if (root->lchild->color == 0 && root->rchild->color == 0) {
        if (has_red_child(root->lchild) || has_red_child(root->rchild)) {
            root->color = 0;
            root->lchild->color = root->rchild->color = 1;
        }
        return root;
    } else if (root->lchild->color == 0 && has_red_child(root->lchild)) {
        if (root->lchild->rchild->color == 0) {
            root->lchild = left_rotate(root->lchild);
        }
        root = right_rotate(root);
    } else if (root->rchild->color == 0 && has_red_child(root->rchild)) {
        if (root->rchild->lchild->color == 0) {
            root->rchild = right_rotate(root->rchild);
        }
        root = left_rotate(root);
    } else {
        return root;
    }
    root->color = 0;
    root->lchild->color = root->rchild->color = 1;
    return root;
}


RBTNode *__insert(RBTNode *root, int key) {// 插入
    if (root == NIL) return init(key);
    if (root->key == key) return root;
    else if (root->key < key) root->rchild = __insert(root->rchild, key);
    else root->lchild = __insert(root->lchild, key);
    return insert_maintain(root);
}

RBTNode *insert(RBTNode *root, int key) {
    root = __insert(root, key);
    root->color = 1;
    return root;
}


刪除操作:

刪除的策略:為了調整和少操作,在刪除點以后割去,不管這給點是什么顏色窟却,直接把刪除點的顏色疊加到他爹的點上,這樣他爹的顏色就是1呻逆,2夸赫,這兩種,然后需要維護的是顏色出現(xiàn)有2的情況咖城。

刪除的時候分為三種大情況:
1.刪除點的度為2
2.刪除點的度為1
3.刪除點的度為0

刪除度2茬腿,1,0:找前驅或者后繼宜雀,交換值切平,刪掉前驅后繼
因為是一層一層下去的,遞歸回去的時候一層一層的維護辐董。

刪除的維護:

刪除的情況

這個時候的關鍵點是雙重黑點的兄弟點悴品,1和4點愛是什么顏色就是什么顏色,因為不影響所以不確定郎哭。

1.雙重黑的2點的兄弟點是紅色(如圖此時是3點)他匪,那么來一個以雙重黑2點的父親為根節(jié)點(此時是1)開始的右旋,調整后讓3為根節(jié)點夸研,3點改成黑色邦蜜,然后這個時候2點的父親是1點,在1點看亥至,看1點的左兒子(2點的兄弟)是不是黑色悼沈,不是就繼續(xù)調整,直到進入第2步姐扮。

2.雙重黑的2點的兄弟點是黑色(如圖此時是3點):

  • 雙重黑點(根節(jié)點左兒子)的兄弟節(jié)點右兒子(根節(jié)點右兒子的右兒子)的(3點的右兒子)是黑色絮供,那么以3點右旋,4點成為3的父親茶敏,3點變成紅色,雙重黑的父親左旋惊搏,4變成根節(jié)點忧换,4點顏色變成雙重黑父親顏色,雙重黑父親顏色變成黑色亚茬,雙重黑顏色減去一層
  • 雙重黑點(根節(jié)點左兒子)的兄弟節(jié)點右兒子(根節(jié)點右兒子的右兒子)的(3點的右兒子)是紅色,那么以3點父親為root刹缝,左旋3點成為根節(jié)點,3點顏色變成雙重黑父親顏色颈将,雙重黑父親顏色變成黑色,雙重黑顏色減去一層

刪除與刪除調整操作:

RBTNode *erase_maintain(RBTNode *root) { // 刪除策略
    if (root->lchild->color != 2 && root->rchild->color != 2) return root;
    #define UNFINE(a, b) (root->a->color == 2 && root->b->color == 1 && !has_red_child(root->b)) 
    if (UNFINE(lchild, rchild) || UNFINE(rchild, lchild)) {
        root->color += 1;
        root->lchild->color -= 1;
        root->rchild->color -= 1;
        return root;
    }
    #undef  UNFINE
    if (root->lchild->color == 2) {
        if (root->rchild->color == 0) {
            root = left_rotate(root);
            root->color = 1;
            root->lchild->color = 0;
            root->lchild = erase_maintain(root->lchild);
            return root;
        }
        root->lchild->color = 1;
        if (root->rchild->rchild->color != 0) {
            root->rchild = right_rotate(root->rchild);
            root->rchild->color = 1;
            root->rchild->rchild->color = 0;
        }
        root = left_rotate(root);
        root->color = root->lchild->color;
    } else {
        if (root->lchild->color == 0) {
            root = right_rotate(root);
            root->color = 1;
            root->rchild->color = 0;
            root->rchild = erase_maintain(root->rchild);
            return root;
        }
        root->rchild->color = 1;
        if (root->lchild->lchild->color != 0) {
            root->lchild = left_rotate(root->lchild);
            root->lchild->color = 1;
            root->lchild->lchild->color = 0;
        }
        root = right_rotate(root);
        root->color = root->rchild->color;
    }
    root->lchild->color = root->rchild->color = 1;
    return root;
}

RBTNode *__erase(RBTNode *root, int key) { // 刪除
    if (root == NIL) return NIL;
    if (root->key < key) root->rchild = __erase(root->rchild, key);
    else if (root->key > key) root->lchild = __erase(root->lchild, key);
    else {
        if (root->lchild != NIL && root->rchild != NIL) {
            RBTNode *temp = preacessor(root);
            root->key = temp->key;
            root->lchild = __erase(root->lchild, temp->key);
        } else {
            RBTNode *temp = (root->lchild == NIL ? root->rchild : root->lchild);
            temp->color += root->color;
            free(root);
            return temp;
        }
    }
    return erase_maintain(root);
}

RBTNode *erase(RBTNode *root, int key) {
    root = __erase(root, key);
    root->color = 1;
    return root;
} 

其他結構操作:

typedef struct RBTNode {
    int key;
    int color;
    struct RBTNode *lchild, *rchild;
} RBTNode;


RBTNode *NIL;
__attribute__((constructor))
void init_NIL() {
    NIL = (RBTNode *)malloc(sizeof(RBTNode));
    NIL->key = 0;
    NIL->color = 1;
    NIL->lchild = NIL->rchild = NIL;
}

RBTNode *init(int key) {
    RBTNode *q = (RBTNode *)malloc(sizeof(RBTNode));
    q->key = key;
    q->color = 0;
    q->lchild = q->rchild = NIL;
    return q;
}

RBTNode *left_rotate(RBTNode *root) {
    RBTNode *temp = root->rchild;
    root->rchild = temp->lchild;
    temp->lchild = root;
    return temp;
}

RBTNode *right_rotate(RBTNode *root) {
    RBTNode *temp = root->lchild;
    root->lchild = temp->rchild;
    temp->rchild = root;
    return temp;
}

int has_red_child(RBTNode *root) {
    return root->lchild->color == 0 || root->rchild->color == 0;
}

RBTNode *preacessor(RBTNode *root) {
    RBTNode *temp = root->lchild;
    while (temp->rchild != NIL) temp = temp->rchild;
    return temp;
}

void  clear(RBTNode *root) {
    if (root == NIL) return ;
    clear(root->lchild);
    clear(root->rchild);
    free(root);
    return ;
}

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市疑务,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌知允,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,366評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件温鸽,死亡現(xiàn)場離奇詭異,居然都是意外死亡涤垫,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,521評論 3 395
  • 文/潘曉璐 我一進店門竟终,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蝠猬,“玉大人,你說我怎么就攤上這事统捶∮苈” “怎么了?”我有些...
    開封第一講書人閱讀 165,689評論 0 356
  • 文/不壞的土叔 我叫張陵喘鸟,是天一觀的道長。 經(jīng)常有香客問我崎淳,道長愕把,這世上最難降的妖魔是什么森爽? 我笑而不...
    開封第一講書人閱讀 58,925評論 1 295
  • 正文 為了忘掉前任咐鹤,我火速辦了婚禮,結果婚禮上雕旨,老公的妹妹穿的比我還像新娘捧请。我一直安慰自己,他們只是感情好疹蛉,可當我...
    茶點故事閱讀 67,942評論 6 392
  • 文/花漫 我一把揭開白布可款。 她就那樣靜靜地躺著,像睡著了一般闺鲸。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上悉罕,一...
    開封第一講書人閱讀 51,727評論 1 305
  • 那天立镶,我揣著相機與錄音,去河邊找鬼嗜逻。 笑死欣范,一個胖子當著我的面吹牛,可吹牛的內容都是我干的恼琼。 我是一名探鬼主播,決...
    沈念sama閱讀 40,447評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼蛙卤,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了神年?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,349評論 0 276
  • 序言:老撾萬榮一對情侶失蹤已日,失蹤者是張志新(化名)和其女友劉穎栅屏,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體护奈,經(jīng)...
    沈念sama閱讀 45,820評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡哥纫,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,990評論 3 337
  • 正文 我和宋清朗相戀三年蛀骇,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片擅憔。...
    茶點故事閱讀 40,127評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡雕欺,死狀恐怖棉姐,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情伞矩,我是刑警寧澤,帶...
    沈念sama閱讀 35,812評論 5 346
  • 正文 年R本政府宣布苛让,位于F島的核電站湿诊,受9級特大地震影響厅须,放射性物質發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,471評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望放可。 院中可真熱鬧吴侦,春花似錦备韧、人聲如沸织堂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,017評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽早像。三九已至卢鹦,卻和暖如春劝堪,著一層夾襖步出監(jiān)牢的瞬間秒啦,已是汗流浹背帝蒿。 一陣腳步聲響...
    開封第一講書人閱讀 33,142評論 1 272
  • 我被黑心中介騙來泰國打工延塑, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人沼撕。 一個月前我還...
    沈念sama閱讀 48,388評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像笼沥,于是被迫代替她去往敵國和親奔浅。 傳聞我的和親對象是個殘疾皇子汹桦,可洞房花燭夜當晚...
    茶點故事閱讀 45,066評論 2 355

推薦閱讀更多精彩內容

  • 1、紅黑樹介紹 紅黑樹又稱R-B Tree寿羞,全稱是Red-Black Tree赂蠢,它是一種特殊的二叉查找樹虱岂,紅黑樹的...
    文哥的學習日記閱讀 9,875評論 1 35
  • 紅黑樹(英語:Red–black tree)是一種自平衡二叉查找樹,是在計算機科學中用到的一種數(shù)據(jù)結構蔑滓,典型的用途...
    卡巴拉的樹閱讀 15,209評論 11 113
  • 0.目錄 1.算法導論的紅黑樹本質上是2-3-4樹 2.紅黑樹的結構和性質 3.紅黑樹的插入 4.紅黑樹的刪除 5...
    王偵閱讀 2,483評論 1 2
  • 上周和大家聊完信用卡如何分期蚜迅,在里面我提到了花唄谁不,花唄是芝麻信用體系中的一個部分徽诲,在這期馏段,我和大家聊一聊芝麻信用院喜。...
    妮可龍姬閱讀 670評論 0 2
  • 能改變行為的信息才有資格叫做知識喷舀。 最近這位老先生頻頻出現(xiàn)在各種場景爸邢,我想有兩個原因:1杠河、你想發(fā)財浇辜,他是讀書人里最...
    元寶爸爸閱讀 489評論 0 0