【數據結構】紅黑樹 C語言代碼

連看帶寫花了三天,中途被指針引用搞得暈暈乎乎的。 插入和刪除的調整過程沒有看原理,只看了方法,直接照着寫的。算法

看了兩份資料,一份是算法導論第12-13章, 另外一份是網上的資料http://blog.csdn.net/v_JULY_v/article/details/6105630spa

下面C代碼是我根據 算法導論的僞碼寫的。.net

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef int DataType;

typedef struct RBNode
{
    RBNode *parent, *left, *right; //指向結點的父結點、左右孩子結點
    DataType key;  //結點數據
    int color; //顏色 紅(r) 或 黑(b)
}RBNode; //定義紅黑樹結點
 

RBNode Nil;
RBNode * nil = &Nil;


void left_rotate( RBNode * &T, RBNode * x) //左旋  x必定不能有引用 由於若是引用後 x與y->parent就是等價的了, y->parent改變 x就會改變
{
    RBNode * y; 
    y = x->right;
    /************第一部分 y的左孩子 與 x間關聯*************/
    x->right = y->left;      //x認右孩子
    if(y->left != nil)
    {
        y->left->parent = x;  //孩子認parent
    }
    /************第一部分 y的左孩子 與 x間關聯 end*************/

    /************第二部分 y 與 x的parent 關聯*************/
    y->parent = x->parent;   //y認 x的parent爲本身的parent   //y的parent與x的地址是同樣的

    int isroot = 0;
    if(x->parent == nil)    //x的parent根據本身的狀況 認y爲左或右孩子
    {
        isroot = 1;
    }
    else if(x == x->parent->left)
    {
        x->parent->left = y;
    }
    else
    {
        x->parent->right = y;
    }
    /************第二部分 y 與 x的parent 關聯 end*************/

    /************第部分 x 與 y的關聯 *************/
    y->left = x;  //y認x爲孩子
    x->parent = y; //x認y爲parent
    /************第部分 x 與 y的關聯 end*************/
    if(isroot == 1)
    {
        T = y;
    }
}

void right_rotate(RBNode * &T, RBNode * x) //右旋
{
    RBNode * y; 
    y = x->left;

    x->left = y->right;

    if(y->right != nil)
    {
        y->right->parent = x;
    }

    y->parent = x->parent;
    int isroot = 0;
    if(x->parent == nil)
    {
        isroot = 1;
    }
    else if(x == x->parent->right)
    {
        x->parent->right = y;
    }
    else
    {
        x->parent->left = y;
    }

    y->right = x;
    x->parent = y;

    if(isroot == 1)
    {
        T = y;
    }
}

void rb_insert_fixup(RBNode * &T, RBNode * z) //紅黑樹插入後的調整  注意z不能要引用 由於調整的過程當中z的值做爲位置標記會改變 但咱們不但願樹的結構由於z而變化
{

    RBNode * y;
        while(z->parent->color == 'r')
        {
            if(z->parent == z->parent->parent->left)    //z的parent是左子的狀況
            {
                //copy(z->parent->parent->right, y);
                y = z->parent->parent->right;
                if(y->color == 'r')        //狀況1 z的parent和uncle都是紅色 把這兩個紅色染成黑色 把grandparent染成紅色 令z = grandparent 再次循環
                {
                    y->color = 'b';
                    z->parent->color = 'b';
                    z->parent->parent->color = 'r';
                    z = z->parent->parent;
                }
                else if(z == z->parent->right)  //當前節點的父節點是紅色,叔叔節點是黑色,當前節點是其父節點的右子 對策:當前節點的父節點作爲新的當前節點,以新當前節點爲支點左旋。
                {
                    z = z->parent;
                    left_rotate(T, z);
                }
                else //當前節點的父節點是紅色,叔叔節點是黑色,當前節點是其父節點的左子 解法:父節點變爲黑色,祖父節點變爲紅色,在祖父節點爲支點右旋
                {
                    z->parent->color = 'b';
                    z->parent->parent->color = 'r';
                    right_rotate(T, z->parent->parent);
                }
            }
            else //z的parent是右子的狀況
            {
                y = z->parent->parent->left;
                if(y->color == 'r')
                {
                    z->parent->color = 'b';
                    y->color = 'b';
                    z->parent->parent->color = 'r';
                    z = z->parent->parent;
                }
                else if(z == z->parent->left)
                {
                    z = z->parent;
                    right_rotate(T, z);
                }
                else
                {
                    z->parent->color = 'b';
                    z->parent->parent->color = 'r';
                    left_rotate(T, z->parent->parent);
                }
            }
        }

    if(z->parent == nil)
    {
        z->color = 'b';
        return;
    }
    else
    {
        return;
    }
}

void rb_insert(RBNode * &T, RBNode * z)  //紅黑樹 插入工做 注意 z不要有引用 
{
    RBNode * y = nil;
    RBNode * x = T;
    while(x != nil)  //找到z適當的插入位置
    {
        y = x;
        if(z->key < x->key)
            x = x->left;
        else
            x = x->right;
    }

    z->parent = y;
    if(y == nil)  //parent 認孩子老是麻煩一些的 畢竟要區分是左是右 是否爲根
    {
        T = z;
    }
    else if(z->key < y->key)
    {
        y->left = z;
    }
    else
    {
        y->right = z;
    }

    //對新插入的點處理, 染成紅色
    z->left = nil;
    z->right = nil;
    z->color = 'r';
    
    //調整紅黑樹
    rb_insert_fixup(T, z);

}

RBNode * rb_findmax(RBNode * z)  //找到以z爲樹根的樹的最大結點
{
    while(z->right != nil)
    {
        z = z->right;
    }
    return z;
}

RBNode * rb_findmin(RBNode * z)  //找到以z爲樹根的樹的最小結點
{
    while(z->left != nil)
    {
        z = z->left;
    }
    return z;
}

RBNode * rb_successor(RBNode * z) //找z的後繼
{
    if(z->right != nil)
    {
        return rb_findmin(z->right);  //若是z的right不爲空 後繼就是z的右子樹中最小的點
    }
    else
    {
        RBNode * y = z->parent;
        while(y != nil && z == y->right)
        {
            z = y;
            y = y->parent;
        }
        return y;
    }
}

void rb_delete_fixup(RBNode * &T, RBNode * x)
{
    RBNode* w;
    while(x != T && x->color == 'b')
    {
        if(x == x->parent->left)
        {
            w = x->parent->right;
            if(w->color == 'r')
            {
                w->color = 'b';
                x->parent->color = 'r';
                left_rotate(T, x->parent);
                
                w = x->parent->right;
            }
            if(w->left->color == 'b' && w->right->color == 'b')
            {
                w->color = 'r';
                x = x->parent;
            }
            else
            {
                if(w->right->color == 'b')
                {
                    w->left->color = 'b';
                    w->color = 'r';
                    right_rotate(T, w);
                    w = x->parent->right;
                }    

                w->color = x->parent->color;
                x->parent->color = 'b';
                w->right->color = 'b';
                left_rotate(T, x->parent);
                x = T;
            }        
        }
        else
        {
            w = x->parent->left;
            if(w->color == 'r')
            {
                w->color = 'b';
                x->parent->color = 'r';
                right_rotate(T, x->parent);
                
                w = x->parent->left;
            }
            if(w->left->color == 'b' && w->right->color == 'b')
            {
                w->color = 'r';
                x = x->parent;
            }
            else if(w->left->color == 'b')
            {
                if(w->left->color == 'b')
                {
                    w->right->color = 'b';
                    w->color = 'r';
                    left_rotate(T, w);
                    w = x->parent->left;
                }
            
                w->color = x->parent->color;
                x->parent->color = 'b';
                w->left->color = 'b';
                right_rotate(T, x->parent);
                x = T;
            }        
        }
    }
    x->color = 'b';
}

RBNode * rb_delete(RBNode * &T, RBNode * z) //紅黑樹 刪除節點
{
    //y 肯定刪除的結點是z仍是z的後繼
    RBNode * y;
    y = (z->left == nil || z->right == nil) ? z : rb_successor(z);

    //x 是y的非nil子女 或是 nil
    RBNode * x;
    x = (y->left != nil) ? y->left : y->right;

    //無條件令x的parent = y的parent 
    x->parent = y->parent;

    //刪除y 創建x與y的parent之間的聯繫
    if(y->parent == nil)
    {
        T = x;
    }
    else if(y == y->parent->left)
    {
        y->parent->left = x;
    }
    else
    {
        y->parent->right = x;
    }

    //若是y!=z 將y的數據拷貝到z
    if(y != z)
    {
        //z的顏色不變
        z->parent = y->parent;
        z->left = y->left;
        z->right = y->right;
        z->key = y->key;
    }

    if(y->color == 'b')
    {
        rb_delete_fixup(T, x);
    }
    return y;
}
int main()
{
    nil->color = 'b';  //葉子結點都是黑的
    nil->left = nil;
    nil->right = nil;
    nil->parent = nil;
    RBNode *T;
    T = nil;
    RBNode data[10];
    for(int i = 0; i < 10; i++)
    {
        data[i].key = i + 1;
        RBNode * z = &data[i];
        rb_insert(T, z);
    }

    RBNode * x = T->left->left;
    rb_delete(T, x);

    return 0;
}
相關文章
相關標籤/搜索