紅黑樹原始碼實現
繼上一篇《思考紅黑樹》 自己親自動手把紅黑樹實現一遍,發現理論成功了要轉換為實際程式碼還是有點難度的,困難點主要在於一些邊界點的確定。花了兩小時才把所有的東西調通,還是需要進一步提高自己的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);
}
相關文章
- js實現紅黑樹JS
- 用Js實現紅黑樹JS
- 結合 TreeMap 原始碼分析紅黑樹在 java 中的實現原始碼Java
- 紅黑樹的原理以及實現
- Java實現紅黑樹(平衡二叉樹)Java二叉樹
- 【資料結構】實現紅黑樹!!!資料結構
- 紅黑樹深入剖析及Java實現Java
- 2-3-4樹對應紅黑樹的實現,紅黑樹的融會貫通!!!
- 紅黑樹
- 思考紅黑樹
- Java原始碼閱讀之TreeMap(紅黑樹) - JDK1.8Java原始碼JDK
- 紅黑樹核心程式碼分析(JAVA)Java
- 瞭解紅黑樹的起源,理解紅黑樹的本質
- Java集合原始碼分析之基礎(六):紅黑樹(RB Tree)Java原始碼
- 徹底理解紅黑樹及JavaJDK1.8TreeMap原始碼分析JavaJDK原始碼
- 紅黑樹詳解
- 淺談紅黑樹
- 【轉】理解紅黑樹
- 紅黑樹左右旋
- 從紅黑樹的本質出發,徹底理解紅黑樹!
- 死磕 java集合之TreeMap原始碼分析(二)——紅黑樹全解析Java原始碼
- 死磕 java集合之TreeMap原始碼分析(三)——紅黑樹全解析Java原始碼
- 死磕 java集合之TreeMap原始碼分析(一)——紅黑樹全解析Java原始碼
- 死磕 java集合之TreeMap原始碼分析(四)——紅黑樹全解析Java原始碼
- 紅黑樹新增刪除
- 演算法導論學習--紅黑樹詳解之刪除(含完整紅黑樹程式碼)演算法
- 【演算法】手撕紅黑樹(上)—— 基本性質以及插入實現(附帶程式碼實現)演算法
- 資料結構--紅黑樹資料結構
- 平衡二叉查詢樹:紅黑樹
- 一個高效能的go 紅黑樹 map, 模擬STL實現Go
- 資料結構之「紅黑樹」資料結構
- Java基礎-理解紅黑樹(插入)Java
- ava 集合 | 紅黑樹 | 前置知識
- JAVA集合:TreeMap紅黑樹深度解析Java
- 圖解集合7:紅黑樹概念、紅黑樹的插入及旋轉操作詳細解讀圖解
- 【乾貨】幾個口訣幫你記憶紅黑樹的操作實現
- 死磕 java集合之TreeMap原始碼分析(二)- 內含紅黑樹分析全過程Java原始碼
- 死磕 java集合之TreeMap原始碼分析(三)- 內含紅黑樹分析全過程Java原始碼