红黑树的c语言实现

    不得不说《算法导论》是一本非常厉害的书!我主要参考了《算法导论》和网络上其他一些优秀的红黑书原理的资料,实现了这个红黑树的代码。很有意义,在整个过程中虽然大部分的时间还是看着书上的伪代码在敲c,但是整个原理已经大致在心中有了一个轮廓,为什么要这么实现红黑树那?前人是怎么想出来的那?路漫漫其修远兮,吾将上下而求索!希望自己有一天也能设计出这么精妙的数据结构算法。这篇文章之后我还将会实现一下avl树,这个树我一直耿耿于怀!先附上一些代码,再说说自己最深的感触。
/*************************************************************************
    > File Name: rb_tree.c
    > Author: jeff zhu
    > Mail: [email protected] 
    > Created Time: 2016年08月30日 星期二 22时08分53秒
 ************************************************************************/

#include 
#include 
#include 

#define RED 1
#define BLACK 2
#define NIL INT_MIN

typedef int EleType;
typedef struct rb_tree_node {
    struct rb_tree_node *parent;
    struct rb_tree_node *left;
    struct rb_tree_node *right;
    EleType key;
    int color;
}NODE;

typedef struct rb_tree {
    NODE *root;
    NODE *nil;
}RBTREE;

void init_rb_tree_root (RBTREE *T) ;
NODE *create_rb_tree_node (RBTREE T , EleType key) ;
void rb_tree_insert (RBTREE *T , NODE *x) ;
void rotate_right (RBTREE *T , NODE *y) ;
void rotate_left (RBTREE *T , NODE *x) ;
void rb_tree_insert_fixup (RBTREE *T , NODE *x) ;
void travel_tree (RBTREE *T , NODE *node) ;
NODE* minimum_rb_tree (RBTREE *T , NODE *x) ;
void rb_tree_delete_fixup (RBTREE *T , NODE *x) ;
void rb_tree_delete (RBTREE *T , NODE *z) ;

int main () {
   RBTREE T;
   init_rb_tree_root (&T);
   NODE *temp;

   int flag;
   while (scanf ("%d" , &flag) , flag != -1) {
       NODE *temp = create_rb_tree_node (T , flag);
       rb_tree_insert (&T , temp);
   }
   rb_tree_delete (&T , T.root);
   travel_tree (&T , T.root);
}

void init_rb_tree_root (RBTREE *T) {
    T->root = NULL;
    T->nil = (NODE *) malloc (sizeof (NODE));
    T->nil->parent = NULL;
    T->nil->left = NULL;
    T->nil->right = NULL;
    T->nil->key = NIL;
    T->nil->color = BLACK;
}

NODE *create_rb_tree_node (RBTREE T , EleType key) { 
    // create a red-black-tree and its default color is RED
    NODE *temp = (NODE *) malloc (sizeof (NODE));
    temp->key = key;
    temp->color = RED;
    temp->parent = NULL;
    temp->left = T.nil;
    temp->right = T.nil;

    return temp;
}

void rb_tree_insert (RBTREE *T , NODE *x) {
    NODE *temp = T->root;
    NODE *log = T->nil;

    if (temp == NULL) {
        T->root = x;
        x->left = T->nil;
        x->right = T->nil;
        x->parent = T->nil;
    }else {
        while (temp != T->nil) {
            log = temp;
            if (x->key > temp->key)
                temp = temp->right;
            else
                temp = temp->left;
        }
        if (log->key < x->key)
            log->right = x;
        else
            log->left = x;
        x->parent = log;
    }
    rb_tree_insert_fixup (T , x);
}

void rb_tree_insert_fixup (RBTREE *T , NODE *x) {
    // this function is to fixup the rb-tree after calling rb_tree_insert
    while (x->parent->color == RED) {
        if (x->parent == x->parent->parent->left) {
            NODE *y = x->parent->parent->right;
            if (y->color == RED) {
                y->color = BLACK;
                x->parent->color = BLACK;
                x->parent->parent->color = RED;
                x = x->parent->parent;
            }else if (y->color == BLACK) {
                if (x == x->parent->right) {
                    x = x->parent;
                    rotate_left (T , x);
                }
                x->parent->color = BLACK;
                x->parent->parent->color = RED;
                rotate_right (T , x->parent->parent);
            }
        }else {
            NODE *y = x->parent->parent->left;
            if (y->color == RED) {
                y->color = BLACK;
                x->parent->color = BLACK;
                x->parent->parent->color = RED;
                x = x->parent->parent;
            }else if (y->color == BLACK) {
                if (x == x->parent->left) {
                    x = x->parent;
                    rotate_right (T , x);
                }
                x->parent->color = BLACK;
                x->parent->parent->color = RED;
                rotate_left (T , x->parent->parent);
            }
        }
    }
    T->root->color = BLACK;
}   

void rotate_left (RBTREE *T , NODE *x) {
    NODE *y = x->right;

    x->right = y->left;
    if (y->left != T->nil)
        y->left->parent = x;
    y->parent = x->parent;
    if (x->parent == T->nil)
        T->root = y;
    else if (x == x->parent->left)
        x->parent->left = y;
    else
        x->parent->right = y;
    x->parent = y;
    y->left = x;
}

void rotate_right (RBTREE *T , NODE *y) {
    NODE *x = y->left;

    y->left = x->right;
    if (x->right != T->nil)
        x->right->parent = y;
    x->parent = y->parent;
    if (y->parent == T->nil)
        T->root = x;
    else if (y == y->parent->left)
        y->parent->left = x;
    else
        y->parent->right = x;
    y->parent = x;
    x->right = y;
}

void travel_tree (RBTREE *T , NODE *node) {
    if (node != T->nil) {
        travel_tree (T , node->left);
        printf ("this node's color is %d\n" , node->color);
        printf ("this node's key is %d\n" , node->key);
        printf ("\n");
        travel_tree (T , node->right);
    }
}

void transplant (RBTREE *T , NODE *x , NODE *y) {
    if (x->parent == T->nil)
        T->root = y;
    else if (x == x->parent->left)
        x->parent->left = y;
    else
        x->parent->right = y;

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

NODE* minimum_rb_tree (RBTREE *T , NODE *x) {
    NODE *y = T->nil;
    NODE *temp = x;
        
    while (temp != T->nil) {
        y = temp;
        temp = temp->left;
    }
    return y;
}

void rb_tree_delete (RBTREE *T , NODE *z) {
    NODE *y = z;
    NODE *x;
    int y_original_color = y->color;

    if (z->left == T->nil) {
        x = z->right;
        transplant (T , z , z->right);
        free (z);
    }else if (z->right == T->nil) {
        x = z->right;
        transplant (T , z , z->left);
        free (z);
    }else  {
        y = minimum_rb_tree (T , z->right);
        y_original_color = y->color;
        x = y->right;
        if (y->parent == z) {
            x->parent = y;
            transplant (T , z , y);
            y->left = z->left;
            z->left->parent = y;
            y->color = z->color;
            free (z);
        }else {
            transplant (T , y , y->right);
            y->right = z->right;
            y->right->parent = y;
            transplant (T , z , y);
            y->left = z->left;
            y->left->parent = y;
            y->color = z->color;
            free (z);
        }
    }
    if (y_original_color == BLACK)
        rb_tree_delete_fixup (T , x);
}

void rb_tree_delete_fixup (RBTREE *T , NODE *x) {
    NODE *w;

    while (x != T->root && x->color == BLACK) {
        if (x == x->parent->left) {
            w = x->parent->right;
            if (w->color == RED) {
                w->color = BLACK;
                x->parent->color = RED;
                rotate_left (T , x->parent);
                w = x->parent->right;
            }
            if (w->left->color == BLACK && w->right->color == BLACK) {
                w->color == BLACK;
                x = x->parent;
            }else {
                if (w->left->color == RED && w->right->color == BLACK) {
                    w->left->color == BLACK;
                    w->color == RED;
                    rotate_right (T , w);
                    w = x->parent->right;
                }
                w->color = w->parent->color;
                w->parent->color = BLACK;
                w->right->color = BLACK;
                rotate_left (T , x->parent);
                x = T->root;
            } 
        }
        else {
            w = x->parent->left;
            if (w->color == RED) {
                w->color = BLACK;
                x->parent->color = RED;
                rotate_right (T , x->parent);
                w = x->parent->left;
            }
            if (w->left->color == BLACK && w->right->color == BLACK) {
                w->color = RED;
                x = x->parent;
            }else {
                if (w->left->color == BLACK && w->right->color == RED) {
                    w->color = RED;
                    w->right->color = BLACK;
                    rotate_right (T , w);
                    w = x->parent->left;
                }
                w->color = w->parent->color;
                w->parent->color = BLACK;
                w->left->color = BLACK;
                rotate_right (T , x->parent);
                x = T->root;
            }
        }
    }
    if (x != T->nil)
        x->color = BLACK;
}

    这个地方我就不再一步一步地去解释原理了,书上包括很多的优秀的博客上都有红黑树详细的解释,我谈谈我在学习的过程中遇到的困难,第一首先要弄懂搜索二叉树的原理,包括插入和删除。知道这个之后我们明白了,在一些情况下,这个树的节点的左右子树可能出现不平衡的状况,导致二叉树的算法的性能大幅下滑,这个时候我们就想要去寻找一种自平衡的二叉树,希望在插入和删除的时候这个树可以自我调节,自我平衡。红黑树就是这样的一种树。而在实现的过程当中,删除的操作最为复杂,这个操作所需要的重要的思想就是x节点。很多思想在代码中并没有反映出来,如果之前位置的y节点的颜色是BLACK,那么这棵树的红黑五大性质就已经被破坏了,所以我们就需要调用rb_tree_delete_fixup来调整,最重要的思想就是,假设x节点自身拥有一重额外的黑色,这个黑色不会在代码上反映,但是却是非常重要的思想。也是这个地方让我思考了最久!我们所需要的做的就是,维护好其他的性质,最后将这一重额外的黑色除去!

    此外非常推荐大家去看看JULY大神的红黑树的文章,非常详细,但是最重要的还是反复去看算法导论上的讲解,真的太厉害了。


你可能感兴趣的:(算法导论)