紅黑樹

    ~~~~資源來自維基百科,這裏算記錄地址
    ~~~~說道epoll,就會說道mmap和紅黑樹,這裏記錄下紅黑樹,學習紅黑樹之前需要先了解二叉搜索樹。

介紹

    ~~~~紅黑樹(英語:Red-black tree)是一種自平衡二叉查找樹,是在計算機科學中用到的一種數據結構,典型的用途是實現關聯數組。
    ~~~~它在1972年由魯道夫·貝爾發明,被稱爲"對稱二叉B樹",它現代的名字源於Leo J. Guibas和Robert Sedgewick於1978年寫的一篇論文。
    ~~~~紅黑樹的結構複雜,但它的操作有着良好的最壞情況運行時間,並且在實踐中高效:它可以在O(logn)O(\log n)時間內完成查找,插入和刪除,這裏的nn是樹中元素的數目。

性質

    ~~~~紅黑樹是每個節點都帶有顏色屬性的二叉查找樹,顏色爲紅色或黑色,在二叉查找樹強制一般要求以外,對於任何有效的紅黑樹我們增加了如下的額外要求。

1.節點是紅色或黑色。
2.根節點是黑色。
3.所有葉子都是黑色的(葉子是NIL節點)。
4.每個紅色節點必須有兩個黑色的子節點。(從每個葉子到根的所有路徑上不能有兩個連續的紅色節點。)
5.從任一節點到其每個葉子的所有簡單路徑都包含相同數目的黑色節點。

紅黑樹圖例:
在這裏插入圖片描述
這些約束確保了紅黑樹的關鍵特性:從根到葉子的最長的可能路徑不多於最短的可能路徑的兩倍長。結果是這個樹大致上是平衡的。因爲操作比如插入、刪除和查找某個值的最壞情況時間都要求與樹的高度成比例,這個在高度上的理論上限允許紅黑樹在最壞情況下都是高效的,而不同於普通的二叉查找樹。

要知道爲什麼這些性質確保了這個結果,注意到性質4導致了路徑不能有兩個毗連的紅色節點就足夠了。最短的可能路徑都是黑色節點,最長的可能路徑有交替的紅色和黑色節點。因爲根據性質5所有最長的路徑都有相同數目的黑色節點,這就表明了沒有路徑能多於任何其他路徑的兩倍長。

在很多樹數據結構的表示中,一個節點有可能只有一個子節點,而葉子節點包含數據。用這種範例表示紅黑樹是可能的,但是這會改變一些性質並使算法複雜。爲此,本文中我們使用"nil葉子"或"空(null)葉子",如上圖所示,它不包含數據而只充當樹在此結束的指示。這些節點在繪圖中經常被省略,導致了這些樹好像同上述原則相矛盾,而實際上不是這樣。與此有關的結論是所有節點都有兩個子節點,儘管其中的一個或兩個可能是空葉子。

操作

    ~~~~因爲每一個紅黑樹也是一個特化的二叉查找樹,因此紅黑樹上的只讀操作與普通二叉查找樹上的只讀操作相同。然而,在紅黑樹上進行插入操作和刪除操作會導致不再符合紅黑樹的性質。恢復紅黑樹的性質需要少量(O(logn))(O(\log n))的顏色變更(實際是非常快速的)和不超過三次樹旋轉(對於插入操作是兩次)。雖然插入和刪除很複雜,但操作時間仍可以保持爲(O(logn))(O(\log n))次。

插入

    ~~~~我們首先以二叉查找樹的方法增加節點並標記它爲紅色。(如果設爲黑色,就會導致根到葉子的路徑上有一條路上,多一個額外的黑節點,這個是很難調整的。但是設爲紅色節點後,可能會導致出現兩個連續紅色節點的衝突,那麼可以通過顏色調換(color flips)和樹旋轉來調整。)下面要進行什麼操作取決於其他臨近節點的顏色。
    ~~~~同人類的家族樹中一樣,我們將使用術語叔父節點來指一個節點的父節點的兄弟節點。注意:

性質1和性質3總是保持着。
性質4只在增加紅色節點、重繪黑色節點爲紅色,或做旋轉時受到威脅。
性質5只在增加黑色節點、重繪紅色節點爲黑色,或做旋轉時受到威脅。

在下面的示意圖中,將要插入的節點標爲NN的父節點標爲PN的祖父節點標爲GN的叔父節點標爲U。在圖中展示的任何顏色要麼是由它所處情形這些所作的假定,要麼是假定所暗含(imply)的。

對於每一種情形,我們將使用C示例代碼來展示。通過下列函數,可以找到一個節點的叔父和祖父節點:

node* grandparent(node *n){
     return n->parent->parent;
 }

 node* uncle(node *n){
     if(n->parent == grandparent(n)->left)
         return grandparent (n)->right;
     else
         return grandparent (n)->left;
 }

情形1:新節點N位於樹的根上,沒有父節點。在這種情形下,我們把它重繪爲黑色以滿足性質2。因爲它在每個路徑上對黑節點數目增加一,性質5符合。

 void insert_case1(node *n){
     if(n->parent == NULL)
         n->color = BLACK;
     else
         insert_case2 (n);
 }

情形2:新節點的父節點P是黑色,所以性質4沒有失效(新節點是紅色的)。在這種情形下,樹仍是有效的。性質5也未受到威脅,儘管新節點N有兩個黑色葉子子節點;但由於新節點N是紅色,通過它的每個子節點的路徑就都有同通過它所取代的黑色的葉子的路徑同樣數目的黑色節點,所以依然滿足這個性質。

void insert_case2(node *n){
     if(n->parent->color == BLACK)
         return; /* 樹仍舊有效*/
     else
         insert_case3 (n);
 }

注意:在下列情形下我們假定新節點的父節點爲紅色,所以它有祖父節點;因爲如果父節點是根節點,那父節點就應當是黑色。所以新節點總有一個叔父節點,儘管在情形4和5下它可能是葉子節點。

情形3:如果父節點P和叔父節點U二者都是紅色,(此時新插入節點N做爲P的左子節點或右子節點都屬於情形3,這裏右圖僅顯示N做爲P左子的情形)則我們可以將它們兩個重繪爲黑色並重繪祖父節點G爲紅色(用來保持性質5)。現在我們的新節點N有了一個黑色的父節點P。因爲通過父節點P或叔父節點U的任何路徑都必定通過祖父節點G,在這些路徑上的黑節點數目沒有改變。但是,紅色的祖父節點G可能是根節點,這就違反了性質2,也有可能祖父節點G的父節點是紅色的,這就違反了性質4。爲了解決這個問題,我們在祖父節點G上遞歸地進行情形1的整個過程。(把G當成是新加入的節點進行各種情形的檢查)
在這裏插入圖片描述

void insert_case3(node *n){
     if(uncle(n) != NULL && uncle (n)->color == RED) {
         n->parent->color = BLACK;
         uncle (n)->color = BLACK;
         grandparent (n)->color = RED;
         insert_case1(grandparent(n));
     }
     else
         insert_case4 (n);
 }

注意:在餘下的情形下,我們假定父節點P是其祖父G的左子節點。如果它是右子節點,情形4和情形5中的左和右應當對調。

情形4:父節點P是紅色而叔父節點U是黑色或缺少,並且新節點N是其父節點P的右子節點而父節點P又是其父節點的左子節點。在這種情形下,我們進行一次左旋轉調換新節點和其父節點的角色;接着,我們按情形5處理以前的父節點P以解決仍然失效的性質4。注意這個改變會導致某些路徑通過它們以前不通過的新節點N(比如圖中1號葉子節點)或不通過節點P(比如圖中3號葉子節點),但由於這兩個節點都是紅色的,所以性質5仍有效。
在這裏插入圖片描述

void insert_case4(node *n){
     if(n == n->parent->right && n->parent == grandparent(n)->left) {
         rotate_left(n);
         n = n->left;
     } else if(n == n->parent->left && n->parent == grandparent(n)->right) {
         rotate_right(n);
         n = n->right;
     }
     insert_case5 (n);
 }

情形5:父節點P是紅色而叔父節點U是黑色或缺少,新節點N是其父節點的左子節點,而父節點P又是其父節點G的左子節點。在這種情形下,我們進行鍼對祖父節點G的一次右旋轉;在旋轉產生的樹中,以前的父節點P現在是新節點N和以前的祖父節點G的父節點。我們知道以前的祖父節點G是黑色,否則父節點P就不可能是紅色(如果P和G都是紅色就違反了性質4,所以G必須是黑色)。我們切換以前的父節點P和祖父節點G的顏色,結果的樹滿足性質4。性質5也仍然保持滿足,因爲通過這三個節點中任何一個的所有路徑以前都通過祖父節點G,現在它們都通過以前的父節點P。在各自的情形下,這都是三個節點中唯一的黑色節點。
在這裏插入圖片描述

void insert_case5(node *n){
     n->parent->color = BLACK;
     grandparent (n)->color = RED;
     if(n == n->parent->left && n->parent == grandparent(n)->left) {
         rotate_right(n->parent);
     } else {
         /* Here, n == n->parent->right && n->parent == grandparent (n)->right */
         rotate_left(n->parent);
     }
 }

注意插入實際上是原地算法,因爲上述所有調用都使用了尾部遞歸。

刪除

    ~~~~如果需要刪除的節點有兩個兒子,那麼問題可以被轉化成刪除另一個只有一個兒子的節點的問題(爲了表述方便,這裏所指的兒子,爲非葉子節點的兒子)。對於二叉查找樹,在刪除帶有兩個非葉子兒子的節點的時候,我們要麼找到它左子樹中的最大元素、要麼找到它右子樹中的最小元素,並把它的值轉移到要刪除的節點中(如在這裏所展示的那樣)。我們接着刪除我們從中複製出值的那個節點,它必定有少於兩個非葉子的兒子。因爲只是複製了一個值(沒有複製顏色),不違反任何性質,這就把問題簡化爲如何刪除最多有一個兒子的節點的問題。它不關心這個節點是最初要刪除的節點還是我們從中複製出值的那個節點。
    ~~~~在本文餘下的部分中,我們只需要討論刪除只有一個兒子的節點(如果它兩個兒子都爲空,即均爲葉子,我們任意將其中一個看作它的兒子)。如果我們刪除一個紅色節點(此時該節點的兒子將都爲葉子節點),它的父親和兒子一定是黑色的。所以我們可以簡單的用它的黑色兒子替換它,並不會破壞性質3和性質4。通過被刪除節點的所有路徑只是少了一個紅色節點,這樣可以繼續保證性質5。另一種簡單情況是在被刪除節點是黑色而它的兒子是紅色的時候。如果只是去除這個黑色節點,用它的紅色兒子頂替上來的話,會破壞性質5,但是如果我們重繪它的兒子爲黑色,則曾經通過它的所有路徑將通過它的黑色兒子,這樣可以繼續保持性質5。
    ~~~~需要進一步討論的是在要刪除的節點和它的兒子二者都是黑色的時候,這是一種複雜的情況(這種情況下該結點的兩個兒子都是葉子結點,否則若其中一個兒子是黑色非葉子結點,另一個兒子是葉子結點,那麼從該結點通過非葉子結點兒子的路徑上的黑色結點數最小爲2,而從該結點到另一個葉子結點兒子的路徑上的黑色結點數爲1,違反了性質5)。我們首先把要刪除的節點替換爲它的兒子。出於方便,稱呼這個兒子爲NN(在新的位置上),稱呼它的兄弟(它父親的另一個兒子)爲SS。在下面的示意圖中,我們還是使用PP稱呼NN的父親,SLS_L稱呼S的左兒子,SRS_R稱呼SS的右兒子。我們將使用下述函數找到兄弟節點:

struct node *
sibling(struct node *n)
{
        if(n == n->parent->left)
                return n->parent->right;
        else
                return n->parent->left;
}

    ~~~~我們可以使用下列代碼進行上述的概要步驟,這裏的函數replacenodereplace_node替換childchildnn在樹中的位置。出於方便,在本章節中的代碼將假定空葉子被用不是NULLNULL的實際節點對象來表示(在插入章節中的代碼可以同任何一種表示一起工作)。

void
delete_one_child(struct node *n)
{
        /*
         * Precondition: n has at most one non-null child.
         */
        struct node *child = is_leaf(n->right)? n->left : n->right;
 
        replace_node(n, child);
        if(n->color == BLACK){
                if(child->color == RED)
                        child->color = BLACK;
                else
                        delete_case1 (child);
        }
        free (n);
}

如果N和它初始的父親是黑色,則刪除它的父親導致通過N的路徑都比不通過它的路徑少了一個黑色節點。因爲這違反了性質5,樹需要被重新平衡。有幾種情形需要考慮:

    ~~~~情形1: N是新的根。在這種情形下,我們就做完了。我們從所有路徑去除了一個黑色節點,而新根是黑色的,所以性質都保持着。

void
delete_case1(struct node *n)
{
        if(n->parent != NULL)
                delete_case2 (n);
}

    ~~~~注意:在情形2、5和6下,我們假定N是它父親的左兒子。如果它是右兒子,則在這些情形下的左和右應當對調。
    ~~~~情形2: S是紅色。在這種情形下我們在N的父親上做左旋轉,把紅色兄弟轉換成N的祖父,我們接着對調N的父親和祖父的顏色。完成這兩個操作後,儘管所有路徑上黑色節點的數目沒有改變,但現在N有了一個黑色的兄弟和一個紅色的父親(它的新兄弟是黑色因爲它是紅色S的一個兒子),所以我們可以接下去按情形4、情形5情形6來處理。
在這裏插入圖片描述

void
delete_case2(struct node *n)
{
        struct node *s = sibling (n);
 
        if(s->color == RED){
                n->parent->color = RED;
                s->color = BLACK;
                if(n == n->parent->left)
                        rotate_left(n->parent);
                else
                        rotate_right(n->parent);
        } 
        delete_case3 (n);
}

情形3: N的父親、S和S的兒子都是黑色的。在這種情形下,我們簡單的重繪S爲紅色。結果是通過S的所有路徑,它們就是以前不通過N的那些路徑,都少了一個黑色節點。因爲刪除N的初始的父親使通過N的所有路徑少了一個黑色節點,這使事情都平衡了起來。但是,通過P的所有路徑現在比不通過P的路徑少了一個黑色節點,所以仍然違反性質5。要修正這個問題,我們要從情形1開始,在P上做重新平衡處理。
在這裏插入圖片描述

void
delete_case3(struct node *n)
{
        struct node *s = sibling (n);
 
        if((n->parent->color == BLACK)&&
(s->color == BLACK)&&
(s->left->color == BLACK)&&
(s->right->color == BLACK)) {
                s->color = RED;
                delete_case1(n->parent);
        } else
                delete_case4 (n);
}

情形4: S和S的兒子都是黑色,但是N的父親是紅色。在這種情形下,我們簡單的交換N的兄弟和父親的顏色。這不影響不通過N的路徑的黑色節點的數目,但是它在通過N的路徑上對黑色節點數目增加了一,添補了在這些路徑上刪除的黑色節點。
在這裏插入圖片描述

void
delete_case4(struct node *n)
{
        struct node *s = sibling (n);
 
        if(n->parent->color == RED)&&
(s->color == BLACK)&&
(s->left->color == BLACK)&&
(s->right->color == BLACK)) {
                s->color = RED;
                n->parent->color = BLACK;
        } else
                delete_case5 (n);
}

情形5: S是黑色,S的左兒子是紅色,S的右兒子是黑色,而N是它父親的左兒子。在這種情形下我們在S上做右旋轉,這樣S的左兒子成爲S的父親和N的新兄弟。我們接着交換S和它的新父親的顏色。所有路徑仍有同樣數目的黑色節點,但是現在N有了一個黑色兄弟,他的右兒子是紅色的,所以我們進入了情形6。N和它的父親都不受這個變換的影響。
在這裏插入圖片描述

void
delete_case5(struct node *n)
{
        struct node *s = sibling (n);
 
        if(s->color == BLACK){ /* this if statement is trivial, 
due to Case 2(even though Case two changed the sibling to a sibling's child, 
the sibling's child can't be red, since no red parent can have a red child). */
// the following statements just force the red to be on the left of the left of the parent, 
// or right of the right, so case six will rotate correctly.
                if((n == n->parent->left)&&
(s->right->color == BLACK)&&
(s->left->color == RED)) { // this last test is trivial too due to cases 2-4.
                        s->color = RED;
                        s->left->color = BLACK;
                        rotate_right (s);
                } else if((n == n->parent->right)&&
(s->left->color == BLACK)&&
(s->right->color == RED)) {// this last test is trivial too due to cases 2-4.
                        s->color = RED;
                        s->right->color = BLACK;
                        rotate_left (s);
                }
        }
        delete_case6 (n);
}

情形6: S是黑色,S的右兒子是紅色,而N是它父親的左兒子。在這種情形下我們在N的父親上做左旋轉,這樣S成爲N的父親(P)和S的右兒子的父親。我們接着交換N的父親和S的顏色,並使S的右兒子爲黑色。子樹在它的根上的仍是同樣的顏色,所以性質3沒有被違反。但是,N現在增加了一個黑色祖先:要麼N的父親變成黑色,要麼它是黑色而S被增加爲一個黑色祖父。所以,通過N的路徑都增加了一個黑色節點。
在這裏插入圖片描述
此時,如果一個路徑不通過N,則有兩種可能性:

它通過N的新兄弟。那麼它以前和現在都必定通過S和N的父親,而它們只是交換了顏色。所以路徑保持了同樣數目的黑色節點。
它通過N的新叔父,S的右兒子。那麼它以前通過S、S的父親和S的右兒子,但是現在只通過S,它被假定爲它以前的父親的顏色,和S的右兒子,它被從紅色改變爲黑色。合成效果是這個路徑通過了同樣數目的黑色節點。

在任何情況下,在這些路徑上的黑色節點數目都沒有改變。所以我們恢復了性質4。在示意圖中的白色節點可以是紅色或黑色,但是在變換前後都必須指定相同的顏色。

void
delete_case6(struct node *n)
{
       struct node *s = sibling (n);

       s->color = n->parent->color;
       n->parent->color = BLACK;

       if(n == n->parent->left){
               s->right->color = BLACK;
               rotate_left(n->parent);
       } else {
               s->left->color = BLACK;
               rotate_right(n->parent);
       }
}

同樣的,函數調用都使用了尾部遞歸,所以算法是原地算法。此外,在旋轉之後不再做遞歸調用,所以進行了恆定數目(最多3次)的旋轉。

代碼實現

#define BLACK 1
#define RED 0
#include <iostream>

using namespace std;

class bst {
private:

    struct Node {
        int value;
        bool color;
        Node *leftTree, *rightTree, *parent;

        Node() : value(0), color(RED), leftTree(NULL), rightTree(NULL), parent(NULL) { }        

        Node* grandparent() {
            if(parent == NULL){
                return NULL;
            }
            return parent->parent;
        }

        Node* uncle() {
            if(grandparent() == NULL) {
                return NULL;
            }
            if(parent == grandparent()->rightTree)
                return grandparent()->leftTree;
            else
                return grandparent()->rightTree;
        }

        Node* sibling() {
            if(parent->leftTree == this)
                return parent->rightTree;
            else
                return parent->leftTree;
        }
    };

    void rotate_right(Node *p){
        Node *gp = p->grandparent();
        Node *fa = p->parent;
        Node *y = p->rightTree;

        fa->leftTree = y;

        if(y != NIL)
            y->parent = fa;
        p->rightTree = fa;
        fa->parent = p;

        if(root == fa)
            root = p;
        p->parent = gp;

        if(gp != NULL){
            if(gp->leftTree == fa)
                gp->leftTree = p;
            else
                gp->rightTree = p;
        }

    }

    void rotate_left(Node *p){
        if(p->parent == NULL){
            root = p;
            return;
        }
        Node *gp = p->grandparent();
        Node *fa = p->parent;
        Node *y = p->leftTree;

        fa->rightTree = y;

        if(y != NIL)
            y->parent = fa;
        p->leftTree = fa;
        fa->parent = p;

        if(root == fa)
            root = p;
        p->parent = gp;

        if(gp != NULL){
            if(gp->leftTree == fa)
                gp->leftTree = p;
            else
                gp->rightTree = p;
        }
    }

    void inorder(Node *p){
        if(p == NIL)
            return;

        if(p->leftTree)
            inorder(p->leftTree);

        cout << p->value << " ";
                
        if(p->rightTree)
            inorder(p->rightTree);
    }

    string outputColor (bool color) {
        return color ? "BLACK" : "RED";
    }

    Node* getSmallestChild(Node *p){
        if(p->leftTree == NIL)
            return p;
        return getSmallestChild(p->leftTree);
    }

    bool delete_child(Node *p, int data){
        if(p->value > data){
            if(p->leftTree == NIL){
                return false;
            }
            return delete_child(p->leftTree, data);
        } else if(p->value < data){
            if(p->rightTree == NIL){
                return false;
            }
            return delete_child(p->rightTree, data);
        } else if(p->value == data){
            if(p->rightTree == NIL){
                delete_one_child (p);
                return true;
            }
            Node *smallest = getSmallestChild(p->rightTree);
            swap(p->value, smallest->value);
            delete_one_child (smallest);

            return true;
        }else{
           return false;
         }
    }

    void delete_one_child(Node *p){
        Node *child = p->leftTree == NIL ? p->rightTree : p->leftTree;
        if(p->parent == NULL && p->leftTree == NIL && p->rightTree == NIL){
            p = NULL;
            root = p;
            return;
        }
        
        if(p->parent == NULL){
            delete  p;
            child->parent = NULL;
            root = child;
            root->color = BLACK;
            return;
        }
        
        if(p->parent->leftTree == p){
            p->parent->leftTree = child;
        } else {
            p->parent->rightTree = child;
        }
        child->parent = p->parent;

        if(p->color == BLACK){
            if(child->color == RED){
                child->color = BLACK;
            } else
                delete_case (child);
        }

        delete p;
    }

    void delete_case(Node *p){
        if(p->parent == NULL){
            p->color = BLACK;
            return;
        }
        if(p->sibling()->color == RED) {
            p->parent->color = RED;
            p->sibling()->color = BLACK;
            if(p == p->parent->leftTree)
                //rotate_left(p->sibling());
                rotate_left(p->parent);
            else
                //rotate_right(p->sibling());
                rotate_right(p->parent);
        }
        if(p->parent->color == BLACK && p->sibling()->color == BLACK
                && p->sibling()->leftTree->color == BLACK && p->sibling()->rightTree->color == BLACK) {
            p->sibling()->color = RED;
            delete_case(p->parent);
        } else if(p->parent->color == RED && p->sibling()->color == BLACK
                && p->sibling()->leftTree->color == BLACK && p->sibling()->rightTree->color == BLACK) {
            p->sibling()->color = RED;
            p->parent->color = BLACK;
        } else {
            if(p->sibling()->color == BLACK) {
                if(p == p->parent->leftTree && p->sibling()->leftTree->color == RED
                        && p->sibling()->rightTree->color == BLACK) {
                    p->sibling()->color = RED;
                    p->sibling()->leftTree->color = BLACK;
                    rotate_right(p->sibling()->leftTree);
                } else if(p == p->parent->rightTree && p->sibling()->leftTree->color == BLACK
                        && p->sibling()->rightTree->color == RED) {
                    p->sibling()->color = RED;
                    p->sibling()->rightTree->color = BLACK;
                    rotate_left(p->sibling()->rightTree);
                }
            }
            p->sibling()->color = p->parent->color;
            p->parent->color = BLACK;
            if(p == p->parent->leftTree){
                p->sibling()->rightTree->color = BLACK;
                rotate_left(p->sibling());
            } else {
                p->sibling()->leftTree->color = BLACK;
                rotate_right(p->sibling());
            }
        }
    }

    void insert(Node *p, int data){
        if(p->value >= data){
            if(p->leftTree != NIL)
                insert(p->leftTree, data);
            else {
                Node *tmp = new Node();
                tmp->value = data;
                tmp->leftTree = tmp->rightTree = NIL;
                tmp->parent = p;
                p->leftTree = tmp;
                insert_case (tmp);
            }
        } else {
            if(p->rightTree != NIL)
                insert(p->rightTree, data);
            else {
                Node *tmp = new Node();
                tmp->value = data;
                tmp->leftTree = tmp->rightTree = NIL;
                tmp->parent = p;
                p->rightTree = tmp;
                insert_case (tmp);
            }
        }
    }

    void insert_case(Node *p){
        if(p->parent == NULL){
            root = p;
            p->color = BLACK;
            return;
        }
        if(p->parent->color == RED){
            if(p->uncle()->color == RED) {
                p->parent->color = p->uncle()->color = BLACK;
                p->grandparent()->color = RED;
                insert_case(p->grandparent());
            } else {
                if(p->parent->rightTree == p && p->grandparent()->leftTree == p->parent) {
                    rotate_left(p);
                    p->color = BLACK;
                    p->leftTree->color = p->rightTree->color = RED;
                } else if(p->parent->leftTree == p && p->grandparent()->rightTree == p->parent) {
                    rotate_right(p);
                    p->color = BLACK;
                    p->leftTree->color = p->rightTree->color = RED;
                } else if(p->parent->leftTree == p && p->grandparent()->leftTree == p->parent) {
                    p->parent->color = BLACK;
                    p->grandparent()->color = RED;
                    rotate_right(p->parent);
                } else if(p->parent->rightTree == p && p->grandparent()->rightTree == p->parent) {
                    p->parent->color = BLACK;
                    p->grandparent()->color = RED;
                    rotate_left(p->parent);
                }
            }
        }
    }

    void DeleteTree(Node *p){
        if(!p || p == NIL){
            return;
        }
        DeleteTree(p->leftTree);
        DeleteTree(p->rightTree);
        delete p;
    }
public:

    bst() {
        NIL = new Node();
        NIL->color = BLACK;
        root = NULL;
    }

    ~bst() {
        if (root)
            DeleteTree (root);
        delete NIL;
    }

    void inorder() {
        if(root == NULL)
            return;
        inorder (root);
        cout << endl;
    }

    void insert (int x) {
        if(root == NULL){
            root = new Node();
            root->color = BLACK;
            root->leftTree = root->rightTree = NIL;
            root->value = x;
        } else {
            insert(root, x);
        }
    }

    bool delete_value (int data) {
        return delete_child(root, data);
    }
private:
    Node *root, *NIL;
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章