看了nginx的源码,其中的定时器采用的数据结构是红黑树,而linux内核中高级数据结构也采用了红黑树,由此可见红黑树效率确实很高。
红黑树是一种局部平衡树,不像AV树那样绝对平衡。但是实现起来也比较复杂,鄙人水平有限,在了解了红黑树原理之后自己用C实现了
红黑树,花了一天时间调试才通过,建议大家也写写,有得地方注释不够清楚,下次补充。
一般的,红黑树,满足以下性质,即只有满足以下全部性质的树,我们才称之为红黑树:
1)每个结点要么是红的,要么是黑的。
2)根结点是黑的。
3)每个叶结点,即空结点(NIL)是黑的。
4)如果一个结点是红的,那么它的俩个儿子都是黑的。
5)对每个结点,从该结点到其子孙结点的所有路径上包含相同数目的黑结点
#include <stdlib.h> #include <stdio.h> #include <string.h> #define RED 1 #define BLOCK 0 //瀹氫箟鑺傜偣 typedef struct myrbtree { int key; //鑺傜偣鍏抽敭瀛楋紝鐢ㄤ互鍞竴鏍囪瘑涓€涓妭鐐� struct myrbtree *parent,*left,*right; int color; //绾㈤粦灞炴€� }Rbnode,*Rbpoint; Rbpoint sentinel ; //鍝ㄥ叺锛屾墍鏈夌殑鍙跺瓙鑺傜偣鎸囧悜鍝ㄥ叺 Rbpoint createnode(int key) //鍒涘缓涓€涓┖鑺傜偣 { Rbpoint new = (Rbpoint)malloc(sizeof(Rbnode)); new->key = key; new->parent = sentinel; new->left = sentinel; new->right = sentinel; new->color = RED; return new; } //涓牴閬嶅巻浜屽樊鏍戝嚱鏁� static void firstroot(Rbpoint root) { Rbpoint tmp = root; if(tmp->left != sentinel) { firstroot(tmp->left); } printf("%d,",tmp->key); if(tmp->right != sentinel) { firstroot(tmp->right); } } //鍒涘缓鏍硅妭鐐瑰嚱鏁� Rbpoint createroot(int key) { Rbpoint root = createnode(key); root->color = BLOCK; //鏍硅妭鐐瑰畾涔変负榛戣壊 } Rbpoint rbbalance(Rbpoint ,Rbpoint ); Rbpoint leftrobate(Rbpoint ,Rbpoint); Rbpoint rightrobate(Rbpoint ,Rbpoint); Rbpoint rbinsert(Rbpoint root,Rbpoint new) //鎻掑叆涓€涓妭鐐癸紝root涓烘牴,new涓烘柊鎻掑叆鑺傜偣 { if(root->color != BLOCK) { printf("root not BLOCK\n"); exit(0); } if(root == sentinel) return new; Rbpoint tmp = root; while(tmp != sentinel) //绾㈤粦鏍戞槸鎺掑簭鏍戯紝鏂拌妭鐐规彃鍏ュ埌鏍戜腑骞舵帓搴� { if(new->key > tmp->key) { if(tmp->right == sentinel) //澶т簬褰撳墠鑺傜偣锛屽垯寰€鍙虫煡鎵剧┖浣嶆彃鍏� { tmp->right = new; new->parent = tmp; break; } else tmp = tmp->right; } else //灏忎簬褰撳墠鑺傜偣锛屽線宸︽煡鎵剧┖浣嶆彃鍏� { if(tmp->left == sentinel) { tmp->left = new; new->parent = tmp; break; } else tmp = tmp->left; } } root = rbbalance(root,new); //鎻掑叆涔嬪悗闇€瑕佸钩琛★紝閫氳繃绉诲姩锛岀炕杞互婊¤冻绾㈤粦鏍戞潯浠� return root; } Rbpoint leftrobate(Rbpoint root,Rbpoint new) //宸︾炕杞� { Rbpoint tmp; if(new == root) return root; tmp = new->parent; if(tmp->parent != sentinel) //缈昏浆鐨勬牴涓烘牴鑺傜偣 { if(tmp->parent->left == tmp) tmp->parent->left = new; else tmp->parent->right = new; new->parent = tmp->parent; tmp->right = new->left; new->left->parent = tmp; tmp->parent = new; new->color = BLOCK; tmp->color = RED; new->left = tmp; return root; } else //缈昏浆鐨勬牴涓嶄负鏍硅妭鐐� { new->parent = sentinel; tmp->right = new->left; new->left->parent = tmp; tmp->parent = new; new->color = BLOCK; tmp->color = RED; new->left = tmp; return new; } } Rbpoint rightrobate(Rbpoint root,Rbpoint new) //鍙堢炕杞紝缈昏浆杩囩▼涓庡乏缈昏浆绫讳技 { Rbpoint tmp; tmp = new->parent; if(tmp->parent != sentinel) { if(tmp->parent->right == tmp) tmp->parent->right = new; else tmp->parent->left = new; new->parent = tmp->parent; tmp->left = new->right; new->right->parent = tmp; tmp->parent = new; new->color = BLOCK; tmp->color = RED; new->right = tmp; return root; } else { new->parent = sentinel; tmp->left = new->right; new->right->parent = tmp; new->color = BLOCK; tmp->color = RED; new->right = tmp; tmp->parent = new; return new; } } Rbpoint rbbalance(Rbpoint root,Rbpoint new) //瀵逛簩鎿︽爲杩涜骞宠 鍖� { Rbpoint tmp; if(new == root) return root; if(new->parent->color == BLOCK) return root; if((new->parent->parent->left != sentinel)&&(new->parent->parent->right != sentinel)&&(new->parent->parent->left->color == RED)&&(new->parent->parent->right->color == RED)) { new->parent->parent->left->color = BLOCK; new->parent->parent->right->color = BLOCK; if(new->parent->parent == root) { root->color = BLOCK; return root; } new->parent->parent->color = RED; tmp = new->parent->parent; rbbalance(root,tmp); } else if((new->parent->left == new)&&(new->parent->parent->left == new->parent)) { return rightrobate(root,new->parent); } else if((new->parent->right == new)&&(new->parent->parent->right== new->parent)) { return leftrobate(root,new->parent); } else if((new->parent->right == new)&&(new->parent->parent->left == new->parent)) { root = leftrobate(root,new); return rightrobate(root,new); } else if((new->parent->left==new)&&(new->parent->parent->right == new->parent)) { root = rightrobate(root,new); return leftrobate(root,new); } } Rbpoint rbfind(Rbpoint root,int key) //閫氳繃閿煡鎵炬爲涓殑鑺傜偣 { Rbpoint tmp = root; while(tmp->key != key) { if(tmp->key > key) { tmp = tmp->left; continue; } else { tmp = tmp->right; continue; } } return tmp; } Rbpoint findmin(Rbpoint root,Rbpoint right) //鏌ユ壘鏍戜腑鐨勬渶灏忚妭鐐� { if(right == sentinel) return root; Rbpoint tmp = right; while(tmp->left != sentinel) tmp = tmp->left; return tmp; } Rbpoint freenode(Rbpoint root,Rbpoint node) //閲婃斁涓€涓妭鐐� { if(node->parent == root) node->parent->right = node->right; else if(node->key > node->parent->key) node->parent->right = node->right; else node->parent->left = node->right; if(node->right != sentinel) node->right->parent = node->parent; free(node); } Rbpoint rbdelete(Rbpoint root,int key) //鍒犻櫎涓€涓妭鐐� { Rbpoint delz = rbfind(root,key); if((delz == root)&&(delz->left == delz->right)) { free(root); return sentinel; } Rbpoint tmpy = findmin(delz,delz->right); Rbpoint tmpx; if(tmpy != delz) tmpx = tmpy->right; else { tmpy->right = tmpy->left; tmpy->left = sentinel; tmpx = tmpy->right; } delz->key = tmpy->key; tmpy->key = key; Rbpoint tmp = tmpy->parent; if(tmpy->color == RED) { freenode(delz,tmpy); return root; } freenode(delz,tmpy); if((tmpx!=sentinel)&&(tmpx->color == RED)) { tmpx->color = BLOCK; return root; } int flag = 1,color; Rbpoint tmpw ; Rbpoint tmpp ; while(flag) { if(((tmpx == sentinel)&&(tmpx == tmp->left))||((tmpx != sentinel)&&(tmpx->key < tmpx->parent->key))) { if(tmpx == sentinel) { tmpw = tmp->right; tmpp = tmp; } else { tmpw = tmpx->parent->right; tmpp = tmpx->parent; } if(tmpw->color == RED) { tmpw->color = BLOCK; tmpp->color = RED; root = leftrobate(root,tmpw); continue; } if((tmpw->color == BLOCK)&&(tmpw->right!=sentinel)&&(tmpw->right->color == RED)) { color = tmpw->color; tmpw->color = tmpp->color; tmpp->color = color; tmpw->right->color = BLOCK; root = leftrobate(root,tmpw); return root; } if((tmpw->color == BLOCK)&&(tmpw->left!=sentinel)&&(tmpw->left->color==RED)&&(tmpw->right!=sentinel)&&(tmpw->right->color==BLOCK)) { color = tmpw->color; tmpw->color = tmpw->left->color; tmpw->left->color = color; root = rightrobate(root,tmpw->left); continue; } if(tmpw->color == BLOCK) { tmpw->color = RED; if(tmpp->color == RED) { tmpp->color = BLOCK; return root; } if(tmpp->parent == sentinel) return root; tmpx = tmpw->parent; continue; } } else { if(tmpx != sentinel) { tmpw = tmpx->parent->left; tmpp = tmpx->parent; } else { tmpw = tmp->left; tmpp = tmp; } if(tmpw->color == RED) { tmpw->color = BLOCK; tmpp->color = RED; root = rightrobate(root,tmpw); continue; } if((tmpw->color == BLOCK)&&(tmpw->left!=sentinel)&&(tmpw->left->color == RED)) { color = tmpw->color; tmpw->color = tmpp->color; tmpp->color = color; tmpw->left->color = BLOCK; root = rightrobate(root,tmpw); return root; } if((tmpw->color == BLOCK)&&(tmpw->left!=sentinel)&&(tmpw->left->color==BLOCK)&&(tmpw->right!=sentinel)&&(tmpw->right->color==RED)) { color = tmpw->color; tmpw->color = tmpw->right->color; tmpw->right->color = color; root = leftrobate(root,tmpw->right); continue; } if(tmpw->color == BLOCK) { tmpw->color = RED; if(tmpp->color == RED) { tmpp->color = BLOCK; return root; } if(tmpp->parent == sentinel) return root; tmpx = tmpw->parent; continue; } } } } void testpc(Rbpoint root,Rbpoint test) { if(test == root) return ; if(test->key > test->parent->key) { if(test->parent->right != test) { printf("insert err %d\n",test->key); exit(0); } } else { if(test->parent->left != test) { printf("insert err %d\n",test->key); exit(0); } } } void midroot(Rbpoint root) //鍏堟牴閬嶅巻 { if(root!=sentinel) printf("%d(%d),",root->key,root->color); if(root->left!=sentinel) midroot(root->left); if(root->right!=sentinel) midroot(root->right); //printf("\n"); } int main(int argc,char **argv) { sentinel = (Rbpoint)malloc(sizeof(Rbnode)); printf("test createnode...\n"); Rbpoint root = createroot(1); printf("test.key:%d,test.color:%d\n***************\n",root->key,root->color); printf("test insert....\n"); Rbpoint test = createnode(2); root = rbinsert(root,test); int keytest[10000]; int i; for(i=5;i<1000;i++) { test = createnode(i); root = rbinsert(root,test); testpc(root,test); } firstroot(root); midroot(root); printf("test firstroot done:.....\n"); for(i=10;i<450;i++) { root = rbdelete(root,i); firstroot(root); printf("\n"); midroot(root); printf("\n"); } printf("test firstroot:.....\n"); }