紅黑樹(shù)C++ 實(shí)現(xiàn)

這是依賴《算法導(dǎo)論》的內(nèi)容編寫(xiě)的代碼。
這個(gè)數(shù)據(jù)結(jié)構(gòu)的實(shí)現(xiàn),我認(rèn)為是一個(gè)從非專(zhuān)業(yè)的程序員到專(zhuān)業(yè)程序員的轉(zhuǎn)折點(diǎn),這個(gè)數(shù)據(jù)結(jié)構(gòu)的設(shè)計(jì)已經(jīng)完全不同于數(shù)學(xué)理論可以考量的地步婿失,完全是一個(gè)算法的設(shè)計(jì)。

紅黑樹(shù)的實(shí)現(xiàn)主要有四點(diǎn)注意:

  1. 牢記紅黑樹(shù)的定義
  2. 理解左旋和右旋啄寡,以及左旋和右旋的意義
  3. 牢記插入的三種特殊CASE
  4. 牢記刪除的四種特殊CASE

其他部分都是基礎(chǔ)的二叉搜索樹(shù)的內(nèi)容豪硅,所以如果對(duì)這部分掌握不夠,需要從這部分學(xué)習(xí)这难。

#include <vector>
#include <assert.h>
#include <stdio.h>
using namespace std;

enum E_COLOR {
    BLACK,
    RED
};

struct RBNode {
    RBNode(int k, E_COLOR c) :
        key(k), color(c), p(nullptr), left(nullptr), right(nullptr)
    { }
    RBNode(int k, E_COLOR c, RBNode * ptr1, RBNode * ptr2, RBNode * ptr3) :
        key(k), color(c), p(ptr1), left(ptr2), right(ptr3)
    { }

    int key;
    E_COLOR color;
    RBNode * p;
    RBNode * left;
    RBNode * right;
};

class RBTree {
public:
    RBTree() {
        NIL = new RBNode(0, BLACK);
        NIL->left = NIL;
        NIL->right = NIL;
        NIL->p = NIL;

        root = NIL;
    }
    ~RBTree() {
        Clear();
        delete NIL;
    }

    RBNode * FindKey(int key) {
        RBNode * pNode = root;

        while (pNode != NIL) {
            if (pNode->key < key) {
                pNode = pNode->right;
            }
            else if (pNode->key > key) {
                pNode = pNode->left;
            }
            else {
                return pNode;
            }
        }

        return nullptr;
    }

    RBNode * FindInsertPos(int key) {
        RBNode * pNode = root;
        while (pNode != NIL) {
            if (pNode->key < key) {
                if (pNode->right == NIL) {
                    return pNode;
                }
                else {
                    pNode = pNode->right;
                }
            }
            else if (pNode->key > key) {
                if (pNode->left == NIL) {
                    return pNode;
                }
                else {
                    pNode = pNode->left;
                }
            }
            else {
                return NIL;
            }
        }

        return NIL;
    }

    RBNode * FindDeletePos(int key) {
        RBNode * pNode = root;

        while (pNode != NIL) {
            if (pNode->key < key) {
                pNode = pNode->right;
            }
            else if (pNode->key > key) {
                pNode = pNode->left;
            }
            else {
                return pNode;
            }
        }

        return NIL;
    }

    void InsertKey(int key) {

        RBNode * pNode = FindInsertPos(key);
        if (root != NIL && pNode == NIL) {
            return;
        }
        RBNode * new_node = new RBNode(key, RED, NIL, NIL, NIL);

        if (pNode == NIL) {
            root = new_node;
        }
        else if (pNode->key < key) {
            pNode->right = new_node;
            new_node->p = pNode;
        }
        else {
            pNode->left = new_node;
            new_node->p = pNode;
        }

        InsertAdjust(new_node);
    }

    void InsertAdjust(RBNode * cur_node) {
        if (root == cur_node) {
            cur_node->color = BLACK;
            NIL->left = cur_node;
            cur_node->p = NIL;
        }
        else if (cur_node->p->color == RED) {
            RBNode * grandpa = cur_node->p->p;
            RBNode * pa = cur_node->p;
            RBNode * uncle = NIL;
            if (grandpa->left == cur_node->p) {
                uncle = grandpa->right;
                if (uncle->color == RED) {
                    pa->color = BLACK;
                    uncle->color = BLACK;
                    grandpa->color = RED;
                    InsertAdjust(grandpa);
                }
                else {
                    if (pa->right == cur_node) {
                        left_rotate(pa);
                        pa = cur_node;
                    }
                    right_rotate(grandpa);
                    grandpa->color = RED;
                    pa->color = BLACK;
                }
            }
            else {
                uncle = grandpa->left;
                if (uncle->color == RED) {
                    pa->color = BLACK;
                    uncle->color = BLACK;
                    grandpa->color = RED;
                    InsertAdjust(grandpa);
                }
                else {
                    if (pa->left == cur_node) {
                        right_rotate(pa);
                        pa = cur_node;
                    }
                    left_rotate(grandpa);
                    grandpa->color = RED;
                    pa->color = BLACK;
                }
            }
        }
    }



    RBNode * FindSuccessor(RBNode * z) {  // assume z have right tree
        assert(z->right != NIL);

        RBNode * p = z->right;
        while (p->left != NIL) {
            p = p->left;
        }
        return p;
    }

    void DeleteKey(int key) {
        RBNode * z = FindDeletePos(key);
        if (z == NIL) return ;

        RBNode * y = NIL;
        if (z->left == NIL || z->right == NIL) {
            y = z;
        }
        else {
            y = FindSuccessor(z);
            swap(y->key, z->key);
        }

        RBNode * yp = y->p;
        RBNode * ychild = y->left != NIL ? y->left : y->right;

        ychild->p = yp;
        if (yp->left == y) {
            yp->left = ychild;
        }
        else {
            yp->right = ychild;
        }

        if (yp == NIL) {
            root = ychild;
        }

        if (y->color == BLACK)
            DeleteAdjust(ychild);

        delete y;
    }

    void DeleteAdjust(RBNode *cur_node) {
        if (cur_node == root
            || cur_node->color == RED) {
            cur_node->color = BLACK;
        }
        else {
            RBNode * x = cur_node;
            RBNode * y = x->p;
            if (y->left == x) {
                RBNode * z = y->right;
                RBNode * zleft = z->left;
                RBNode * zright = z->right;

                if (z->color == RED) {
                    left_rotate(y);
                    y->color = RED;
                    z->color = BLACK;
                    DeleteAdjust(x);
                }
                else if (zleft->color == BLACK && zright->color == BLACK) {
                    z->color = RED;
                    DeleteAdjust(y);
                }
                else if (zleft->color == RED && zright->color == BLACK) {
                    right_rotate(z);
                    zleft->color = BLACK;
                    z->color = RED;
                    DeleteAdjust(x);
                }
                else {
                    left_rotate(y);
                    y->color = BLACK;
                    z->color = RED;
                    zright->color = BLACK;
                }

            }
            else {
                RBNode * z = y->left;
                RBNode * zleft = z->left;
                RBNode * zright = z->right;

                if (z->color == RED) {
                    right_rotate(y);
                    y->color = RED;
                    z->color = BLACK;
                    DeleteAdjust(x);
                }
                else if (zleft->color == BLACK && zright->color == BLACK) {
                    z->color = RED;
                    DeleteAdjust(y);
                }
                else if (zleft->color == BLACK && zright->color == RED) {
                    left_rotate(z);
                    zright->color = BLACK;
                    z->color = RED;
                    DeleteAdjust(x);
                }
                else {
                    right_rotate(y);
                    y->color = BLACK;
                    z->color = RED;
                    zleft->color = BLACK;
                }
            }
        }
    }

    void left_rotate(RBNode * x) { // y 是 x 的右孩子
        RBNode * y = x->right;
        RBNode * xp = x->p;
        RBNode * yleft = y->left;

        y->p = xp;
        if (xp->left == x) {
            xp->left = y;
        }
        else {
            xp->right = y;
        }

        y->left = x;
        x->p = y;

        x->right = yleft;
        yleft->p = x;

        if (root == x) {
            root = y;
        }
    }

    void right_rotate(RBNode * x) { // y是 x的左孩子
        RBNode * y = x->left;
        RBNode * xp = x->p;
        RBNode * yright = y->right;

        y->p = xp;
        if (xp->left == x) {
            xp->left = y;
        }
        else {
            xp->right = y;
        }

        y->right = x;
        x->p = y;
        x->left = yright;
        yright->p = x;

        if (root == x) {
            root = y;
        }
    }

    void Output(RBNode * pNode) {
        if (pNode == NIL) return;

        Output(pNode->left);
        printf("%d ", pNode->key);
        Output(pNode->right);
    }

    void Output() {
        Output(root);
    }

    void Clear(RBNode * pNode) {
        if (pNode == NIL) {
            return;
        }

        Clear(pNode->left);
        Clear(pNode->right);
        delete pNode;
    }

    void Clear() {
        Clear(root);
        root = NIL;
    }

private:
    RBNode * root;
private:
    RBNode * NIL;
};

int main(int argc, char ** argv) {
    RBTree tree;
    vector<int> vecNum = { 1, 3, 2, 4, 5, 6, 10, 2, 19, -1, 20, 50, 22 };

    
    for (int i = 0; i < vecNum.size(); ++i) {
        tree.InsertKey(vecNum[i]);
    }

    tree.Output();
    puts("");

    for (int i = 0; i < vecNum.size(); ++i) {
        tree.DeleteKey(vecNum[i]);
    }


    tree.Output();
    puts("");
    tree.DeleteKey(50);

    tree.Output();
    puts("");

    tree.InsertKey(1000);
    tree.Output();
    puts("");

    return 0;
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市葡秒,隨后出現(xiàn)的幾起案子姻乓,更是在濱河造成了極大的恐慌嵌溢,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,820評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蹋岩,死亡現(xiàn)場(chǎng)離奇詭異赖草,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)剪个,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,648評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)秧骑,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人扣囊,你說(shuō)我怎么就攤上這事乎折。” “怎么了侵歇?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,324評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵骂澄,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我惕虑,道長(zhǎng)坟冲,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,714評(píng)論 1 297
  • 正文 為了忘掉前任溃蔫,我火速辦了婚禮健提,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘伟叛。我一直安慰自己私痹,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,724評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布痪伦。 她就那樣靜靜地躺著侄榴,像睡著了一般。 火紅的嫁衣襯著肌膚如雪网沾。 梳的紋絲不亂的頭發(fā)上癞蚕,一...
    開(kāi)封第一講書(shū)人閱讀 52,328評(píng)論 1 310
  • 那天,我揣著相機(jī)與錄音辉哥,去河邊找鬼桦山。 笑死,一個(gè)胖子當(dāng)著我的面吹牛醋旦,可吹牛的內(nèi)容都是我干的恒水。 我是一名探鬼主播,決...
    沈念sama閱讀 40,897評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼饲齐,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼钉凌!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起捂人,我...
    開(kāi)封第一講書(shū)人閱讀 39,804評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤御雕,失蹤者是張志新(化名)和其女友劉穎矢沿,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體酸纲,經(jīng)...
    沈念sama閱讀 46,345評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡捣鲸,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,431評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了闽坡。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片栽惶。...
    茶點(diǎn)故事閱讀 40,561評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖疾嗅,靈堂內(nèi)的尸體忽然破棺而出外厂,到底是詐尸還是另有隱情,我是刑警寧澤宪迟,帶...
    沈念sama閱讀 36,238評(píng)論 5 350
  • 正文 年R本政府宣布酣衷,位于F島的核電站,受9級(jí)特大地震影響次泽,放射性物質(zhì)發(fā)生泄漏穿仪。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,928評(píng)論 3 334
  • 文/蒙蒙 一意荤、第九天 我趴在偏房一處隱蔽的房頂上張望啊片。 院中可真熱鬧,春花似錦玖像、人聲如沸紫谷。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,417評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)笤昨。三九已至,卻和暖如春握恳,著一層夾襖步出監(jiān)牢的瞬間瞒窒,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,528評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工乡洼, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留崇裁,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,983評(píng)論 3 376
  • 正文 我出身青樓束昵,卻偏偏與公主長(zhǎng)得像拔稳,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子锹雏,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,573評(píng)論 2 359

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