紅黑樹原始碼實現

小灰馬發表於2013-08-24

繼上一篇《思考紅黑樹》 自己親自動手把紅黑樹實現一遍,發現理論成功了要轉換為實際程式碼還是有點難度的,困難點主要在於一些邊界點的確定。花了兩小時才把所有的東西調通,還是需要進一步提高自己的C功力。

直接貼程式碼吧,有需要的拿去用,我自己也留著以後拿來玩玩。

這份程式碼肯定是需要根據實際環境進行修改的,前兩天大概掃了一下 《Linux核心中的紅黑樹》裡面的程式碼,發現自己寫的程式碼水平跟大神寫的還是有些差距啊...加油吧。


//rb_tree.h

#include <stdio.h>
#include <stdlib.h>
#ifndef RB_TREE
#define RB_TREE
typedef 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 node
struct 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 1
			if(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{
				//case2
				if(z == z->parent->right){  
					z = z->parent;
					rbtree_left_roate(root,z);
				}
				//case3
				z->parent->color = RB_BLACK;
				z->parent->parent->color = RB_RED;
				rbtree_right_roate(root,z->parent->parent);
			}
		}else{
			//case 1
			if(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);
				}
				//case3
				z->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 delete
	if(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 node
	if(delete->left != rb_nil){
		inherit = delete->left;
	}else{
		inherit = delete->right;
	}
	//connect inherit to delete node's parent
	parent = delete->parent;
	inherit->parent = parent;
        //connect delete node's parent to inherit
	if(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){
			//case1
			if(z->parent->right->color == RB_RED){
				z->parent->color = RB_RED;
				z->parent->right->color = RB_BLACK;
				rbtree_left_roate(root,z->parent);
			}else{
				//case2
				if(z->parent->right->left->color == RB_BLACK && z->parent->right->right->color == RB_BLACK){
					z->parent->right->color = RB_RED;
					z = z->parent;
				}else{
					//case3
					if(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);
					}
					//case4
					z->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{
			//case1
			if(z->parent->left->color == RB_RED){
				z->parent->color = RB_RED;
				z->parent->left->color = RB_BLACK;
				rbtree_right_roate(root,z->parent);
			}else{
				//case2
				if(z->parent->left->left->color == RB_BLACK && z->parent->left->right->color == RB_BLACK){
					z->parent->left->color = RB_RED;
					z = z->parent;
				}else{
					//case3
					if(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);
					}
					//case4
					z->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_nil
void 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_nil
void 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);
}






相關文章