紅黑二叉樹

//
// 五條屬性:
// 1.每個節點或是紅色的,或是黑色的。
// 2.根節點是黑色的。
// 3.每個葉結點(NIL)是黑色的。
// 4.如果一個結點是紅色的,則它的兩個子結點都是黑色的。
// 5.對每個結點,從該結點到其所有後代葉結點的簡單路徑上
// 均包含相同數目的黑色結點。
//

//http://blog.csdn.net/v_JULY_v/article/details/6105630
//https://github.com/torvalds/linux/blob/master/lib/rbtree.c
//https://github.com/torvalds/linux/blob/master/include/linux/rbtree_augmented.h
//https://github.com/torvalds/linux/blob/master/include/linux/rbtree.h

#include "common.h"
#include "RBTree.h"

static RB_NODE* RbSearch(int key, RB_NODE* root);
static RB_NODE* RbInsert(RB_NODE* head, RB_NODE* node);
static RB_NODE* InsertFixup(RB_NODE *,RB_NODE *);
static RB_NODE* LeftRotate(RB_NODE* head, RB_NODE* node);
static RB_NODE* RightRotate(RB_NODE* head, RB_NODE* node);
static RB_NODE* RbTransplant(RB_NODE* head,RB_NODE* u,RB_NODE* v);

static RB_NODE* RbDeleteFixup(RB_NODE* head, RB_NODE* x);
static RB_NODE* RbDelete(RB_NODE* head, RB_NODE* z);
static void TreePrint(RB_NODE* head);
static void LevelOrderWalk(RB_NODE* node);

void PrintT(RB_NODE* head)
{
    RB_NODE *left=NULL, *right=NULL;
    RB_NODE *left1=NULL,*left2=NULL,*right1=NULL,*right2=NULL;
    RB_NODE *left31=NULL,*left32=NULL,*right31=NULL,*right32=NULL,*left33=NULL,*left34=NULL,*right33=NULL,*right34=NULL;
    if(head)
    {
        left=head->left;
        right=head->right;
    }

    if(left)
        printf("[%d]",left->key);
    if(head)
    printf("[%d]",head->key);
    if(right)
        printf("[%d]",right->key);
    printf("\n-----\n");

    if(left)
    {
        left1 = left->left;
        left2 = left->right;
    }
    if(right)
    {
        right1 = right->left;
        right2 = right->right;
    }
    if(left1)
        printf("[%d]",left1->key);
    if(left2)
        printf("[%d]",left2->key);
    if(right1)
        printf("[%d]",right1->key);
    if(right2)
        printf("[%d]",right2->key);
    printf("\n-----\n");

    if(left1)
    {
        left31 = left1->left;
        left32 = left1->right;
    }
    if(left2)
    {
        left33 = left2->left;
        left34 = left2->right;
    }
    if(right1)
    {
        right31 = right1->left;
        right32 = right1->right;
    }
    if(right2)
    {
        right33 = right2->left;
        right34 = right2->right;
    }
    if(left31)
        printf("[%d]",left31->key);    
    if(left32)
        printf("[%d]",left32->key);
    if(left33)
        printf("[%d]",left33->key);
    if(left34)
        printf("[%d]",left34->key);
    if(right31)
        printf("[%d]",right31->key);
    if(right32)
        printf("[%d]",right32->key);
    if(right33)
        printf("[%d]",right33->key);
    if(right34)
        printf("[%d]",right34->key);
    printf("\n-----\n");
}

void RBTree()
{

    ///////////////////////////////////////
    //二叉樹:
    //              11
    //            2      14
    //         1    7       15
    //            5   8
    //          4
    ///////////////////////////////////////
    ///////////////////////////////////////
    //紅黑樹:
    //              7
    //            2        11
    //         1    5    8    14
    //            4  6    9  13  15
    //         
    ///////////////////////////////////////
    int toBeInsert[] = {11,2,14,1,7,15,5,8,9,4,13,6};
    int i;
    RB_NODE *head = NULL;
    RB_NODE * tmp = NULL;
    RB_NODE* node;
    for(i=0; i<sizeof(toBeInsert)/sizeof(int); i++)
    {
        node = (RB_NODE*)malloc(sizeof(RB_NODE));
        node->key = toBeInsert[i];
        head = RbInsert(head, node);
    }
    //TreePrint(head);
    PrintT(head);
    printf("\n==========\n");
    for(i=0; i<sizeof(toBeInsert)/sizeof(int); i++)
    {
        tmp = RbSearch(toBeInsert[i],head);
        if(tmp)
        {
            printf("%d ",tmp->key);
            head = RbDelete(head, tmp);
            PrintT(head);
            //TreePrint(head);
            printf("\n");
        }
    }
    printf("\n");

}

//三、紅黑樹查找結點  
//----------------------------------------------------  
//rb_search_auxiliary:查找  
//rb_node_t* rb_search:返回找到的結點  
//----------------------------------------------------  
static RB_NODE* RbSearchAuxiliary(int key, RB_NODE* root, RB_NODE** pre)  
{  
    RB_NODE *node = root, *parent = NULL;
    int ret;

    while(node)
    {
        parent = node;
        ret = node->key - key;  
        if (0 < ret)
        {
            node = node->left;  
        }
        else if (0 > ret)
        {  
            node = node->right;
        }  
        else
        {
            return node;  
        }
    }

    if (pre)
    {
        *pre = parent;
    }

    return NULL;
}

//返回上述rb_search_auxiliary查找結果  
RB_NODE* RbSearch(int key, RB_NODE* root)  
{  
    return RbSearchAuxiliary(key, root, NULL);  
}  


RB_NODE* RbInsert(RB_NODE* head, RB_NODE* node)
{
    RB_NODE *tmp = head;
    RB_NODE *pre = NULL;
    //二叉樹的插入動作需要先找到插入位置
    while(tmp != NULL)
    {
        pre = tmp;
        if(node->key < tmp->key)
        {
            tmp = tmp->left;
        }
        else
        {
            tmp = tmp->right;
        }
    }
    if(pre == NULL)
    {
        head = node;
    }
    else if(node->key < pre->key)
    {
        pre->left = node;
    }
    else
    {
        pre->right = node;
    }
    node->p = pre;
    node->color = RED;
    node->left = NULL;
    node->right = NULL;
    head = InsertFixup(head,node);
    return head;
}


//左旋,
//右孩子和top的位置調換,top成爲right的左孩子
//top的左孩子最小依然是top的左孩子
//右孩子的左孩子大於top小於右孩子,經過轉換成爲top的右孩子
//
RB_NODE* LeftRotate(RB_NODE* head, RB_NODE* top)
{
    RB_NODE* right = top->right;
    top->right = right->left;
    if(right->left != NULL)
    {
        right->left->p = top;
    }
    right->p = top->p;
    if(top->p == NULL)
    {
        head = right;
    }
    else if(top == top->p->left)
    {
        top->p->left = right;
    }
    else if(top == top->p->right)
    {
        top->p->right = right;
    }
    right->left = top;
    top->p = right;
    return head;
}

// 右旋 --- 將根的左孩子轉移到根的位置,原來的根成爲新的根的右孩子
//最小值a和最大值r都不變
//中間數據:x--小於原來根y,大於原來根的左孩子x。
//        y        x     
//      x   r -->a   y   
//     a b          b r
//
RB_NODE* RightRotate(RB_NODE* head, RB_NODE* y)
{
    RB_NODE *x = y->left;
    y->left = x->right;
    if(x->right != NULL)
    {
        x->right->p = y;
    }
    x->p = y->p;
    if(y->p == NULL)
    {
        head = x;
    }
    else if(y == y->p->left)
    {
        x->p->left = x;
    }
    else
    {
        x->p->left = x;
    }
    x->right = y;
    y->p = x;
    return head;

}
//
// 五條屬性:
// 1.每個節點或是紅色的,或是黑色的。
// 2.根節點是黑色的。
// 3.每個葉結點(NIL)是黑色的。
// 4.如果一個結點是紅色的,則它的兩個子結點都是黑色的。
// 5.對每個結點,從該結點到其所有後代葉結點的簡單路徑上
// 均包含相同數目的黑色結點。
//
//如果插入的是根結點,由於原樹是空樹,此情況只會違反性質2,因此直接把此結點塗爲黑色;
//如果插入的結點的父結點是黑色,由於此不會違反性質2和性質4,紅黑樹沒有被破壞,所以此時什麼也不做。
//
//出現需要修復的情況必然是插入的結點的父結點是紅色,祖父結點是黑色
//插入修復情況1:如果當前結點的父結點是紅色且祖父結點的另一個子結點(叔叔結點)是紅色
//插入修復情況2:當前節點的父節點是紅色,叔叔節點是黑色,當前節點是其父節點的右子
//插入修復情況3:當前節點的父節點是紅色,叔叔節點是黑色,當前節點是其父節點的左子
//
static RB_NODE* InsertFixup(RB_NODE* head, RB_NODE* node)
{
    RB_NODE *parnt, *grdparnt,*uncle, *tmp;
    while((parnt = node->p) && parnt->color == RED)
    {
        //1.如果z.p(z的父結點)是其父結點的左孩子
        //(1)將其父結點的右孩子設爲y
        //    z.p<z.p.p<y
        grdparnt = parnt->p;
        if(grdparnt->left == parnt)
        {
            uncle = grdparnt->right;
            if(uncle && uncle->color == RED)
            {
                parnt->color = BLACK;
                uncle->color = BLACK;
                grdparnt->color = RED;
                node = grdparnt;
                // case 1:z.p爲RED
                //    z.p是其父結點的左孩子
                //    y爲z.p的右兄弟
                //    y爲RED(規則4)
                //    將z.p和y都置爲BLACK
                //    將z.p.p置爲RED
            }
            else
            {
                if(node == parnt->right)
                {
                    head = LeftRotate(head,parnt);
                    tmp = parnt;
                    parnt = node;
                    node = tmp;
                    //case2:
                    //z.p爲RED
                    //    z.p是其父節點的左孩子
                    //    y爲z.p的右兄弟
                    //    y爲BLACK &&  z是z.p的右孩子
                    //      (規則4)
                    //      z = z.p//指針上移
                    //      左旋
                }
                parnt->color = BLACK;    //case 3
                grdparnt->color = RED;
                head = RightRotate(head,grdparnt);
            }
        }
        else if (grdparnt->right == parnt)
        {
            uncle = grdparnt->left;
            if(uncle && uncle->color == RED)
            {
                parnt->color = BLACK;
                uncle->color = BLACK;
                grdparnt->color = RED;
                node = grdparnt;
            }
            else
            {
                if(node == parnt->left)
                {
                    head = RightRotate(head,parnt);
                    tmp = parnt;
                    parnt = node;
                    node = tmp;
                }
                parnt->color = BLACK;    //case 3
                grdparnt->color = RED;
                head = LeftRotate(head,grdparnt);
            }
        }
    }
    head->color = BLACK;
    return head;
}



static RB_NODE* TreeMinmum(RB_NODE* x)
{
    while(x->left != NULL)
    {
        x = x->left;
    }
    return x;
}
//
//結點替換:將u用v替換掉。
//情況1:被換結點是根,那麼根地址指向v
//情況2:被換結點是一個左孩子,
//情況3:被換結點是一個右孩子
static RB_NODE* RbTransplant(RB_NODE* head,RB_NODE* u,RB_NODE* v)
{
    if(u->p == NULL)
    {
        head = v;
    }
    else if ( u == u->p->left)
    {
        u->p->left = v;
    }
    else
    {
        u->p->right = v;    
    }
    if(v)
    {
        v->p = u->p;
    }
    
    return head;
}

///////////////////////////////////////////////////////////////////////////////////////////
//刪除:用左孩子、右孩子、後繼來替換被刪除的結點。然後根據規則進行重新修整。
// 左孩子爲空就用右孩子,右孩子爲空就用左孩子,有兩個孩子就用後繼。
//
// 紅黑樹屬性:
// 1.每個節點或是紅色的,或是黑色的。
// 2.根節點是黑色的。
// 3.每個葉結點(NIL)是黑色的。
// 4.如果一個結點是紅色的,則它的兩個子結點都是黑色的。
// 5.對每個結點,從該結點到其所有後代葉結點的簡單路徑上
// 均包含相同數目的黑色結點。
//
// //如果y(z)(被刪結點)是紅色,當y被刪除或移動時,紅黑性質仍然保持,原因如下:
// 1.樹中的黑高沒有變化。
// 2.不存在兩個相鄰的紅結點。因爲y在樹中佔據了z的位置,在考慮到z的顏色,樹中y的新位置
// 不可能有兩個相鄰的紅結點。另外,如果y不是z的右孩子,則y的原右孩子x代替y.如果y是紅色,
// 則x一定是黑色,因此用x替代y不可能使兩個紅結點相鄰。
// 3.如果y是紅色,就不可能是根節點,所以根節點仍舊是黑色。
///////////////////////////////////////////////////////////////////////////////////////////
static RB_NODE* RbDelete(RB_NODE* head, RB_NODE* z)
{
    RB_NODE* y = z;
    RB_NODE* x;
    COLOR yOrgClr = y->color;
    if(z->left == NULL)
    {
        x = z->right;
        head = RbTransplant(head,z,z->right);
    }
    else if(z->right == NULL)
    {
        x = z->left;
        head = RbTransplant(head,z,z->left);
    }
    else
    {
        y = TreeMinmum(z->right);
        yOrgClr = y->color;
        x = y->right;
        if(y->p == z)
        {
            if(x)
            x->p = y;        //如果後繼是其子
        }
        else                //如果後繼是其孫輩或孫輩的後輩
        {
            head = RbTransplant(head,y,y->right);
            y->right = z->right;
            y->right->p = y;
        }
        head = RbTransplant(head,z,y);
        y->left = z->left;
        if(y->left)
        {
            y->left->p = y;
        }
        y->color = z->color;//替換之後,顏色復原
    }
    free(z);
    if(yOrgClr == BLACK)
    {
        head = RbDeleteFixup(head,x);
    }
    return head;
}
//
//
static RB_NODE* RbDeleteFixup(RB_NODE* head, RB_NODE* x)
{
    while(x && x->p != NULL && x->color == BLACK)
    {
        RB_NODE* w;
        if(x == x->p->left)    //
        {
            w = x->p->right;
            if(w->color == RED)
            {
                w->color = BLACK;
                x->p->color = RED;
                head = LeftRotate(head,x->p);
                w = x->p->right;
            }
            if(w->left->color == BLACK && w->right->color == BLACK)
            {
                w->color = RED;
                x = x->p;
            }
            else
            {
                if(w->right->color)
                {
                    w->left->color = BLACK;
                    w->color = RED;
                    head = RightRotate(head,w);
                    w = x->p->right;
                }
                w->color = x->p->color;
                x->p->color = BLACK;
                w->right->color = BLACK;
                head = LeftRotate(head,x->p);
                x = head;
            }
            
        }
        else
        {
            w = x->p->left;
            if(w->color == RED)
            {
                w->color = BLACK;
                x->p->color = RED;
                head = RightRotate(head,x->p);
                w = x->p->left;
            }
            if(w->right->color == BLACK && w->left->color == BLACK)
            {
                w->color = RED;
                x = x->p;
            }
            else
            {
                if(w->left->color)
                {
                    w->right->color = BLACK;
                    w->color = RED;
                    head = LeftRotate(head,w);
                    w = x->p->left;
                }
                w->color = x->p->color;
                x->p->color = BLACK;
                w->left->color = BLACK;
                head = RightRotate(head,x->p);
                x = head;
            }
        }
    }
    if(x)
    x->color = BLACK;
    return head;
}

static void TreePrint(RB_NODE* node)
{
    if(node == NULL)
    {
        return ;
    }
    //printf("<%c>",node->data);//先序遍歷p,l,r
    TreePrint(node->left);
    printf("<%d>",node->key);//    中序遍歷l,p,r
    TreePrint(node->right);
    //printf("<%c>",node->data);//後序遍歷
}



//RBTree.h

#ifndef RB_TREE_H
#define RB_TREE_H
#include "common.h"

//302419016
typedef enum{RED,BLACK}COLOR;

typedef struct RB_NODE{
	struct RB_NODE *left,*right,*p;
	int key;
	COLOR color;
}RB_NODE,*RB_TREE;

void RBTree();

#endif



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章