红黑树源码实现

来源:互联网 发布:四灵进阶数据 编辑:程序博客网 时间:2024/04/29 12:48

继上一篇《思考红黑树》 自己亲自动手把红黑树实现一遍,发现理论成功了要转换为实际代码还是有点难度的,困难点主要在于一些边界点的确定。花了两小时才把所有的东西调通,还是需要进一步提高自己的C功力。

直接贴代码吧,有需要的拿去用,我自己也留着以后拿来玩玩。

这份代码肯定是需要根据实际环境进行修改的,前两天大概扫了一下 《Linux内核中的红黑树》里面的代码,发现自己写的代码水平跟大神写的还是有些差距啊...加油吧。


//rb_tree.h

#include <stdio.h>#include <stdlib.h>#ifndef RB_TREE#define RB_TREEtypedef struct{int value;}rbtree_key;typedef struct{int value;}rbtree_data;typedef enum rbtree_color{RB_RED,RB_BLACK}rbtree_color;int rbtree_key_cmp(rbtree_key x,rbtree_key y);typedef struct rbtree_node rbtree_node;//rb tree nodestruct rbtree_node{rbtree_key key;        rbtree_color color;rbtree_data data;rbtree_node *parent;rbtree_node *left;rbtree_node *right;};rbtree_node * rb_nil;static int rb_nil_inited;void rbtree_init_nil();void rbtree_destroy_nil();void rbtree_node_cpy(rbtree_node *source,rbtree_node *dest);rbtree_node * rbtree_search(rbtree_node * t,rbtree_key key);rbtree_node * rbtree_search_iterative(rbtree_node * t,rbtree_key key);rbtree_node * rbtree_min(rbtree_node *t);rbtree_node * rbtree_max(rbtree_node *t);rbtree_node * rbtree_successor(rbtree_node *t);rbtree_node * rbtree_predecessor(rbtree_node *t);        void rbtree_insert(rbtree_node **root,rbtree_node *z);        void rbtree_insert_fixup(rbtree_node **root,rbtree_node *z);void rbtree_delete(rbtree_node **root,rbtree_node *z);void rbtree_delete_fixup(rbtree_node **root,rbtree_node *z);void rbtree_left_roate(rbtree_node **root,rbtree_node *z);void rbtree_right_roate(rbtree_node **root,rbtree_node *z);#endif


rb_tree.c

#include "rb_tree.h"int rbtree_key_cmp(rbtree_key x,rbtree_key y){return y.value-x.value;}void rbtree_node_cpy(rbtree_node *source,rbtree_node *dest){dest->key.value = source->key.value;dest->data.value = source->data.value;}void rbtree_init_nil(){if(!rb_nil_inited){rb_nil = (rbtree_node *)malloc(sizeof(rbtree_node));rb_nil->color = RB_BLACK;rb_nil->parent = rb_nil;rb_nil->left = rb_nil;rb_nil->right = rb_nil;rb_nil_inited = 1;}}void rbtree_destroy_nil(){if(rb_nil_inited){free(rb_nil);rb_nil=NULL;rb_nil_inited = 0;}}rbtree_node * rbtree_search(rbtree_node * t,rbtree_key key){int cmp = rbtree_key_cmp(t->key,key);if(rb_nil == t || 0 == cmp )return t;return cmp<0?rbtree_search(t->left,key):rbtree_search(t->right,key);}rbtree_node * rbtree_search_iterative(rbtree_node * t,rbtree_key key){int cmp = rbtree_key_cmp(t->key,key);while(rb_nil != t && 0!=cmp){t = cmp<0?t->left:t->right;}return t;}rbtree_node * rbtree_min(rbtree_node *t){while(rb_nil != t->left){t = t->left;}return t;}rbtree_node * rbtree_max(rbtree_node *t){while(rb_nil != t->right){t = t->right;}return t;}rbtree_node * rbtree_successor(rbtree_node *t){        rbtree_node * parent;if(rb_nil != t->right){return rbtree_min(t->right);}        parent = t->parent;while(parent != rb_nil  && t == parent->right){t = parent;parent = parent->parent;}        return parent;}rbtree_node * rbtree_predecessor(rbtree_node *t){        rbtree_node * parent;if(rb_nil != t->left){return rbtree_max(t->left);}        parent = t->parent;while(rb_nil != parent && t == parent->left ){t = parent;parent = parent->parent;}        return parent;}void rbtree_insert(rbtree_node **root,rbtree_node *z){int cmp;        rbtree_node *p,*t;if(rb_nil == *root){*root = z;return;}t = *root;while( rb_nil != t){p = t;cmp = rbtree_key_cmp(t->key,z->key);t = cmp<0?t->left:t->right;}if(cmp<0){p->left = z;}else{p->right = z;}        z->parent = p;        z->color = RB_RED;if(z->parent->color == RB_RED){rbtree_insert_fixup(root,z);}}void rbtree_insert_fixup(rbtree_node **root,rbtree_node *z){while(z->parent->color == RB_RED){if(z->parent == z->parent->parent->left){                        //case 1if(z->parent->parent->right->color == RB_RED){z->parent->parent->color = RB_RED;z->parent->parent->left->color = RB_BLACK;z->parent->parent->right->color = RB_BLACK;z = z->parent->parent;}else{//case2if(z == z->parent->right){  z = z->parent;rbtree_left_roate(root,z);}//case3z->parent->color = RB_BLACK;z->parent->parent->color = RB_RED;rbtree_right_roate(root,z->parent->parent);}}else{//case 1if(z->parent->parent->left->color == RB_RED){z->parent->parent->color = RB_RED;z->parent->parent->left->color = RB_BLACK;z->parent->parent->right->color = RB_BLACK;z = z->parent->parent;}else{//case2 if(z == z->parent->left){z = z->parent;rbtree_right_roate(root,z);}//case3z->parent->color = RB_BLACK;z->parent->parent->color = RB_RED;rbtree_left_roate(root,z->parent->parent);}}}(*root)->color = RB_BLACK;}void rbtree_delete(rbtree_node **root,rbtree_node *z){rbtree_node *parent;rbtree_node *inherit;rbtree_node *delete;//find which node to deleteif(z->left != rb_nil && z->right != rb_nil){delete = rbtree_successor(z);rbtree_node_cpy(delete,z);}else{delete = z;}//find the inherit node of the delete nodeif(delete->left != rb_nil){inherit = delete->left;}else{inherit = delete->right;}//connect inherit to delete node's parentparent = delete->parent;inherit->parent = parent;        //connect delete node's parent to inheritif(parent == rb_nil){*root = inherit;}else{if(delete == parent->left){parent->left = inherit;}else{parent->right = inherit;}}if(delete->color = RB_BLACK){rbtree_delete_fixup(root,inherit);}free(delete);return;}void rbtree_delete_fixup(rbtree_node **root,rbtree_node *z){while(z != *root && z->color == RB_BLACK){if(z == z->parent->left){//case1if(z->parent->right->color == RB_RED){z->parent->color = RB_RED;z->parent->right->color = RB_BLACK;rbtree_left_roate(root,z->parent);}else{//case2if(z->parent->right->left->color == RB_BLACK && z->parent->right->right->color == RB_BLACK){z->parent->right->color = RB_RED;z = z->parent;}else{//case3if(z->parent->right->left->color == RB_RED){z->parent->right->left->color = RB_BLACK;z->parent->right->color = RB_RED;rbtree_right_roate(root,z->parent->right);}//case4z->parent->right->color = z->parent->color;z->parent->right->right->color = RB_BLACK;z->parent->color = RB_BLACK;rbtree_left_roate(root,z->parent);break;}}}else{//case1if(z->parent->left->color == RB_RED){z->parent->color = RB_RED;z->parent->left->color = RB_BLACK;rbtree_right_roate(root,z->parent);}else{//case2if(z->parent->left->left->color == RB_BLACK && z->parent->left->right->color == RB_BLACK){z->parent->left->color = RB_RED;z = z->parent;}else{//case3if(z->parent->left->right->color == RB_RED){z->parent->left->right->color = RB_BLACK;z->parent->left->color = RB_RED;rbtree_left_roate(root,z->parent->left);}//case4z->parent->left->color = z->parent->color;z->parent->left->left->color = RB_BLACK;z->parent->color = RB_BLACK;rbtree_right_roate(root,z->parent);break;}}}}z->color = RB_BLACK;}//assume that z's right child is not rb_nilvoid rbtree_left_roate(rbtree_node **root,rbtree_node *z){rbtree_node *right_child;right_child = z->right;//1.z->right = right_child->left;if(right_child->left != rb_nil){right_child->left->parent = z;}//2.right_child->left = z;right_child->parent = z->parent;if(right_child->parent == rb_nil){*root = right_child;        //3.}else if(z == z->parent->left){z->parent->left = right_child;}else{z->parent->right = right_child;}z->parent = right_child;}//assume that z's left child is not rb_nilvoid rbtree_right_roate(rbtree_node **root,rbtree_node *z){rbtree_node *left_child;left_child = z->left;//1.z->left = left_child->right;if(left_child->right != rb_nil){left_child->right->parent = z;}//2.left_child->right = z;left_child->parent = z->parent;if(left_child->parent == rb_nil){*root = left_child;        //3.}else if(z == z->parent->left){z->parent->left = left_child;}else{z->parent->right = left_child;}z->parent = left_child;}

//测试代码  t.c

#include <stdio.h>#include <stdlib.h>#include "lib/rb_tree.h"rbtree_node * rbtree_create(int num);rbtree_node * rbtree_add(rbtree_node **root,int num);void rbtree_destroy(rbtree_node *t);void rbtree_print(rbtree_node * t);rbtree_node * rbtree_find(rbtree_node *t,int num);int main(int argc,char *argv[]){rbtree_node *t,*p,*max,*min;int arr[] = {9,8,11,18,2,5,16,1,8};int i;rbtree_init_nil();t = rbtree_create(10);t->color = RB_BLACK;for(i=0;i<9;i++){rbtree_add(&t,arr[i]);rbtree_print(t);printf("=================\n");}p = rbtree_min(t);printf("%d:%p  p:%p,l:%p,r:%p\n",p->key.value,p,p->parent,p->left,p->right);while((p=rbtree_successor(p)) != rb_nil){printf("%d:%p  p:%p,l:%p,r:%p\n",p->key.value,p,p->parent,p->left,p->right);}        printf("\n");        min = rbtree_min(t);printf("t:%p,min:%p\n",t,min);do{printf("--------------\n");rbtree_print(t);max = rbtree_max(t);printf("%d ",max->key.value);p = max;while((p=rbtree_predecessor(p))!=rb_nil){printf("%d ",p->key.value);}printf("\n");rbtree_delete(&t,max);}while(t!=rb_nil);printf("\nt:%p\n",t);rbtree_destroy(t);rbtree_destroy_nil();return 0;}rbtree_node * rbtree_create(int num){rbtree_node *p;p = (rbtree_node *)malloc(sizeof(rbtree_node));p->key.value = num;p->data.value = 0;p->color = RB_RED;p->left = rb_nil;p->right = rb_nil;p->parent = rb_nil;return p;}rbtree_node * rbtree_add(rbtree_node **root,int num){rbtree_node *p;p = rbtree_create(num);rbtree_insert(root,p);}rbtree_node * rbtree_find(rbtree_node *t,int num){rbtree_key key;key.value = num;        return rbtree_search(t,key);}void rbtree_destroy(rbtree_node *t){        if(rb_nil == t) return;rbtree_node *p;p = t;free(t);if(p->left) rbtree_destroy(p->left);if(p->right) rbtree_destroy(p->right); }void rbtree_print(rbtree_node * t){if(rb_nil == t) return;printf("       %d-%d\n",t->key.value,t->color);printf("      ↙");printf("  ↘\n");if(t->left != rb_nil){printf("     %d-%d",t->left->key.value,t->left->color);}else{printf("     nil-%d",t->left->color);}if(t->right != rb_nil){printf("   %d-%d",t->right->key.value,t->right->color);}else{printf("   nil-%d",t->right->color);}printf("\n");rbtree_print(t->left);rbtree_print(t->right);}