【数据结构】红黑树 C语言代码

连看带写花了三天,中途被指针引用搞得晕晕乎乎的。 插入和删除的调整过程没有看原理,只看了方法,直接照着写的。

看了两份资料,一份是算法导论第12-13章, 另一份是网上的资料http://blog.csdn.net/v_JULY_v/article/details/6105630

下面C代码是我根据 算法导论的伪码写的。

#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;
}

 

posted @ 2014-07-31 22:27  匡子语  阅读(1157)  评论(0编辑  收藏  举报