红黑树C实现

说明文档能够参照红黑树

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

typedef int datatype ;
typedef unsigned int COLOR ;
enum {RED,BLACK};
typedef struct _rb_tree
{
    COLOR color;
    datatype key;
    struct _rb_tree * parent;
    struct _rb_tree * lchild;
    struct _rb_tree * rchild;
}rbtree;

typedef struct _rb_root
{
    rbtree * root = NULL;
}rbroot;

void insert_data(rbroot*T,datatype data);
void left_rotate(rbroot * T,rbtree* node);
void right_rotate(rbroot * T,rbtree* node);
void insert_data(rbroot*T,datatype data);
void insert_item(rbroot*T,rbtree *item);
void insert_fixup(rbroot*T,rbtree* item);
void pre_visit(rbtree * tree);
void rb_transplant(rbroot *T,rbtree * from ,rbtree * to);
void delete_item(rbroot *T,rbtree * item);
void delete_fixup(rbroot *T,rbtree * parent,rbtree * item);
rbtree* tree_minimum(rbtree * tree);

void left_rotate(rbroot * T,rbtree* node)
{
    rbtree *right = NULL;
    right = node->rchild;
    node->rchild = right->lchild;

    if ( NULL != right->lchild )
    {
        right->lchild->parent = node;
    }
    
    right -> parent = node -> parent;

    if ( NULL ==  node -> parent  )
    {
         T->root = right;
    }
    else if( node == node->parent->lchild )
    {
        node->parent->lchild = right;
    }
    else
    {
        node->parent->rchild = right;
    }

    right->lchild = node;
    node->parent = right;
}

void right_rotate(rbroot * T,rbtree* node)
{
    rbtree *left = NULL;
    left = node->lchild;
    node->lchild = left->rchild;

    if ( NULL != left->rchild )
    {
        left->rchild->parent = node;
    }
    
    left -> parent = node -> parent;

    if ( NULL ==  node -> parent  )
    {
         T->root = left;
    }
    else if( node == node->parent->lchild )
    {
        node->parent->lchild = left;
    }
    else
    {
        node->parent->rchild = left;
    }
    left->rchild = node;
    node->parent = left;
}



void insert_data(rbroot*T,datatype data)
{
    rbtree * item = NULL;
    item = ( rbtree * )malloc(sizeof(rbtree));
    item -> lchild = item->rchild = item->parent = NULL;
    item -> key = data;
    item -> color = RED;
    insert_item(T,item);
}

void insert_item(rbroot*T,rbtree *item)
{
    rbtree * pre = NULL , *temp = T->root ;

    while ( NULL != temp )
    {
        pre = temp;
        if (item-> key < temp-> key)
        {
            temp = temp->lchild;
        }
        else
        {
            temp = temp->rchild;
        }
    }

    item->parent = pre;

    if ( pre == NULL )
    {
        T->root = item;
    }
    else if( item -> key < pre -> key )
    {
        pre -> lchild = item;
    }
    else
    {
        pre -> rchild = item;
    }

    insert_fixup(T,item);
}

void insert_fixup(rbroot*T,rbtree* item)
{
    rbtree* uncle = NULL;
    while (NULL != item->parent && RED == item->parent->color)
    {
        if ( item->parent == item -> parent -> parent -> lchild )
        {
            uncle = item -> parent -> parent -> rchild;
            if ( NULL != uncle && uncle->color == RED )
            {
                item -> parent -> color = BLACK;
                uncle -> color = BLACK;
                item -> parent -> parent -> color = RED;
                item = item -> parent -> parent;
            }
            else
            {
                if (item == item->parent->rchild)
                {
                    item = item -> parent;
                    left_rotate(T,item);
                }
                item -> parent -> color = BLACK;
                item -> parent -> parent -> color = RED;
                right_rotate(T,item->parent-> parent);
            }
        }
        else
        {
            uncle = item -> parent -> parent -> lchild;
            if ( NULL != uncle && uncle->color == RED)
            {
                item -> parent -> color = BLACK;
                uncle -> color = BLACK;
                item -> parent -> parent -> color = RED;
                item = item -> parent -> parent;
            }
            else
            {
                if (item == item->parent->lchild)
                {
                    item = item -> parent;
                    right_rotate(T,item);
                }
                item -> parent -> color = BLACK;
                item -> parent -> parent -> color = RED;
                left_rotate(T,item->parent-> parent);
            }
        }
    }
    T->root->color = BLACK;
}

void delete_item(rbroot *T,rbtree * item)
{
    rbtree * replace = NULL,*deletingItem = NULL,*parent = NULL;
    COLOR deletingColor = RED;

    deletingItem = item;
    deletingColor = item->color;
    if (NULL == deletingItem->lchild && NULL == deletingItem->rchild)
    {
        replace = NULL;
        parent = deletingItem->parent;
        if (NULL == deletingItem->parent)
        {
            T->root = NULL;
        }
        else
        {
            rb_transplant(T,deletingItem,replace);
        }
    }
    else if ( NULL == deletingItem->lchild )
    {
        replace = deletingItem->rchild;
        parent = deletingItem->parent;
        rb_transplant(T,deletingItem,replace);
    }
    else if(NULL == deletingItem->rchild)
    {
        replace = deletingItem->lchild;
        parent = deletingItem->parent;
        rb_transplant(T,deletingItem,replace);
    }
    else
    {
        /* 根据前面的条件判断,左右子树已经不会是空。*/
        deletingItem = tree_minimum(deletingItem->rchild);
        /*tree_minimum找到的是一个借点,确定不为空。*/
        deletingColor = deletingItem->color;
        parent = deletingItem->parent;
        replace = deletingItem->rchild;

        if (item == deletingItem->parent)
        {
            /*
                这种就是比较特殊的状况了
                没有左子树,这种的parent的parent就事自己。
                另外一种是由于挂接,并且能够回溯。
                这种若是是右孩子的右孩子为空,就没法回溯,经过给定的方式声明。
            */
            parent = deletingItem;
        }
        else
        {
            rb_transplant(T,deletingItem,deletingItem->rchild);
            deletingItem->rchild = item->rchild;
            deletingItem->rchild->parent = deletingItem;
        }
        rb_transplant(T,item,deletingItem);
        deletingItem->lchild = item->lchild;
        deletingItem->lchild->parent = deletingItem;
        deletingItem->color = item->color;
    }
    if (BLACK == deletingColor)
    {
        delete_fixup(T,parent,replace);
    }
    delete item;
}

void delete_fixup(rbroot *T,rbtree * parent,rbtree * item)
{
    /*失去了一个black节点,那么也就是说原来的这个节点的黑高至少为2,那么兄弟节点确定不为空。*/
    rbtree * brother = NULL;
    while ( item != T->root && (NULL == item || BLACK == item->color ))
    {
        if ( item == parent->lchild )
        {
            brother = parent->rchild;
            if (RED == brother->color)
            {
                /* 
                    parent确定是黑色
                    这样作是为了交换,而后转化为相同子问题。即下面的三种状况。
                    这样就能够统一方便的处理。
                */
                brother -> color = BLACK;
                parent->color = RED;
                left_rotate(T,parent);
                brother = parent->rchild;
            }
            if ( ( NULL == brother->lchild || BLACK == brother->lchild->color ) &&  ( NULL == brother->rchild || BLACK == brother->rchild->color ))
            {
                /*左孩子的黑高下降了,将右孩子的黑高也下降,也就是右孩子设为红,若是父节点为黑,此时子树已经黑高平衡,可是由于下降了黑高,因此须要向上回溯。
                  若是是回溯到了root,则说明,整个下降了一层黑高。
                  若是说是回溯到了父亲节点为红色,也就只须要修改红色为黑色,就能够弥补两边的黑高不平衡了,变黑后,两边的黑高同时+1.
                 */
                brother->color = RED;
                item = parent;
                parent = parent->parent;
            }
            else
            {
                /* 
                    到了这里,说明其中有一个为红,或者两个都为红 
                    这个就能够经过旋转的方式弥补黑高。
                    前面的为何不能够呢?由于旋转没有办法保证必定成功。
                    分析:

                        1. 若是父节点为红:
                            右子树就是黑
                            经过右旋转拉长,再左旋转升高变色平衡。
                            若是右子树的左孩子是空,就会失败,没法进行右旋转。因此只能回溯。
                            若是右子树的左孩子不空,且为黑,也就是黑高>3了。这个时候进行右旋转拉长。再左旋平衡。可是这个过程,右子树的左孩子不平衡。
                            若是右子树的左孩子不空,且为红,也就是如今的这种状况了。
                        2. 若是父节点是黑色:
                            右子树为红,没法旋转,由于嫁接过去的子树仍然不平衡。
                            右子树为黑,如上。
                    为何下面的旋转之后能够呢?
                        1. 兄弟确定有一个孩子为红,也就是说,兄弟确定为黑。
                            左子树为红,则右旋,右边子树黑高不变。
                            坐旋转,嫁接变红,左边黑高变高,由于右子树为红,因此总体的平衡。
                            可是由于
                */
                if ( NULL == brother->rchild || BLACK == brother->rchild->color )
                {
                    /*
                        若是右子树为黑,也就是说左子树为红,这个操做主要是对右子树染红,若是自己就是红色就不用染色了。
                        到了这里,此时的条件就是,兄弟节点必定为黑色。
                        先进行变色右旋转,造成brother的左右平衡,且变高了一个。
                        旋转后须要跟新brother.这个时候的brother的左和新的节点黑高相同。只须要左旋转升高,嫁接变色就能够了。
                        这个操做是为了确保右边为红。
                    */
                    brother->lchild->color = BLACK;
                    brother->color = RED;
                    right_rotate(T,brother);
                    brother = parent->rchild;
                }
                brother->color = parent->color;
                /* brother 即将继承 parent的身份,颜色.*/
                parent->color = BLACK;
                /*parent 也即将降级左旋升高。左树黑高。*/
                brother->rchild->color = BLACK;
                /*由于以前就确保了右孩子为红,变黑右子树左旋转后黑高不变。*/
                left_rotate(T,parent);
                /*旋转以后已经平衡,因此退出循环*/
                item = T->root;
            }
        }
        else
        {
            brother = parent->lchild;
            if (RED == brother->color)
            {
                brother -> color = BLACK;
                parent->color = RED;
                right_rotate(T,parent);
                brother = parent->lchild;
            }
            if ( ( NULL == brother->lchild || BLACK == brother->lchild->color ) && ( NULL == brother->rchild || BLACK == brother->rchild->color ))
            {
                brother->color = RED;
                item = parent;
                parent = parent->parent;
            }
            else
            {
                if ( NULL == brother->lchild || BLACK == brother->lchild->color )
                {
                    brother->rchild->color = BLACK;
                    brother->color = RED;
                    left_rotate(T,brother);
                    brother = parent->lchild;
                }
                brother->color = parent->color;
                parent->color = BLACK;
                brother->lchild->color = BLACK;
                right_rotate(T,parent);
                item = T->root;
            }
        }
    }
    if (NULL != item)
    {
        item->color = BLACK;
    }
}

rbtree* tree_minimum(rbtree * tree)
{
    while(NULL != tree && NULL != tree->lchild )
    {
        tree = tree->lchild;
    }
    return tree;
}

void rb_transplant(rbroot *T,rbtree * deleting ,rbtree * replace)
{
    /* replace来充当继承人,deleting 和 replace 交接完父子关系以后就成了自由人。 */
    if ( NULL == deleting->parent )
    {
        T->root = replace;
    }
    else if( deleting == deleting -> parent -> lchild )
    {
        deleting->parent->lchild = replace;
    }
    else
    {
        deleting->parent->rchild = replace;
    }
    if (NULL !=  replace)
    {
        replace->parent = deleting->parent;
    }
}

void pre_visit(rbtree * tree)
{
    if( NULL != tree )
    {
        pre_visit(tree->lchild);
        printf("%d %s\n",tree->key,tree->color == RED ? "red" : "black");
        pre_visit(tree->rchild);
    }

}

void bh_visit(rbtree * tree,int rbh,int level)
{
    if( NULL != tree )
    {
        bh_visit(tree->lchild,rbh+(tree->lchild == NULL || tree->lchild->color == BLACK),level+1);
        bh_visit(tree->rchild,rbh+(tree->rchild == NULL || tree->rchild->color == BLACK),level+1);
    }
    else
    {
        printf("bh %d level %d\n",rbh,level);
    }
}

int main()
{
    rbroot root;
    datatype datas[] = {1,2,3,4,5,6,7,8,2,3,4,5,6,7,7};
    for( int i = 0 ; i < sizeof(datas)/sizeof(datatype); i++ )
    {
        insert_data(&root,datas[i]);
    }
    pre_visit(root.root);
    bh_visit(root.root,1,1);
    while(root.root && root.root->rchild)
    {
        printf("----------------- %d\n",root.root->key);
        delete_item(&root,root.root->rchild);
        pre_visit(root.root);
    }
    printf("start------after delete\n");
    pre_visit(root.root);
    printf("black high\n");
    bh_visit(root.root,1,1);
    printf("%x\n",root.root);
    return 0;
}
相关文章
相关标签/搜索