红黑树入门
红黑树 (参看《算法导论》)
红黑树是一种平衡二叉树,巧妙地利用结点颜色来简化维护平衡的难度。具有如下性质:
1.红黑树上所有结点要么是红色的,要么是黑色的。
2.红黑树的根节点是黑色的。
3.如果一个结点是红色的,那么他的两个子结点必须是黑色的。
4.对于每一个结点,他左子树的黑色结点数量必然等于右子树的黑色结点数量。
5.所有叶子结点必然是黑色的。
(一)抛弃原有的NULL,所有指向NULL的指针,改为指向一个与普通结点相同的T.null结点,T.null结点颜色固定为黑色,这样便解决了叶子结点的问题,同时根结点的父指针也指向它。
(二)每次新插入结点为红色,这样不影响性质1、4、5,也就是说当插入结点时,只可能影响到性质2或者3,维护起来方便,可以向上维护,(插入结点设为x),如果x为根结点,那么可以直接改成黑色,如果不是,那么判断父结点是不是红色,如果是,说明违背了性质3,可以通过旋转、上升矛盾(直至根)来解决。
(三)删除一个结点,寻找替代的结点,也就是后继,将这个替代点改成与原要删除的点一样的颜色,这么,问题就缩小到替代点原位置可能少了一个黑结点,那么可以通过上升矛盾子树(即令与他相对应的兄弟子树也少一个黑结点,那么便变成父结点所在的子树少了一个黑结点)或者红转黑来解决,需要注意的是不要在维护过程中,违背更多的红黑树性质。
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<string.h> 4 5 #define RED 0 6 #define BLACK 1 7 8 typedef struct node 9 { 10 bool color; //结点颜色,红色或者黑色 11 int data; //数据存放 12 struct node *fa,*lchild,*rchild; //三个指针 13 }RB_Node; 14 15 typedef struct 16 { 17 RB_Node *root; //指向树的根节点 18 RB_Node *null; //在红黑树中用来代替NULL,方便编程 19 }Tree; 20 21 Tree *Tree_Init() 22 { 23 Tree *T; 24 T=(Tree *)malloc(sizeof(Tree)); 25 T->null=(RB_Node *)malloc(sizeof(RB_Node)); 26 T->null->color=BLACK; 27 T->null->lchild=T->null; 28 T->null->rchild=T->null; 29 T->null->fa=T->null; 30 T->root=T->null; 31 return T; 32 } 33 34 RB_Node *Node_Init(Tree *T) 35 { 36 RB_Node *s; 37 s=(RB_Node *)malloc(sizeof(RB_Node)); 38 s->color=RED; 39 s->lchild=T->null; 40 s->rchild=T->null; 41 s->fa=T->null; 42 return s; 43 } 44 45 void RB_Left_Rotate(Tree *T,RB_Node *x) //左旋转,原本为 \ (x在上),旋转为 /(x在下) 46 { 47 RB_Node *y=x->rchild; 48 x->rchild=y->lchild; 49 y->lchild->fa=x; 50 if(x==T->root) T->root=y; 51 else 52 { 53 if(x==x->fa->lchild) x->fa->lchild=y; 54 else x->fa->rchild=y; 55 } 56 y->fa=x->fa; 57 y->lchild=x; 58 x->fa=y; 59 } 60 61 void RB_Right_Rotate(Tree *T,RB_Node *x) //右旋转,原本为 / (x在上),旋转为 \(x在下) 62 { 63 RB_Node *y=x->lchild; 64 x->lchild=y->rchild; 65 y->rchild->fa=x; 66 if(x==T->root) T->root=y; 67 else 68 { 69 if(x==x->fa->lchild) x->fa->lchild=y; 70 else x->fa->rchild=y; 71 } 72 y->fa=x->fa; 73 y->rchild=x; 74 x->fa=y; 75 } 76 77 void RB_Adjust_Insert(Tree *T,RB_Node *x) 78 { 79 while(x->fa->color==RED) 80 { 81 if(x->fa==x->fa->fa->lchild) 82 { 83 RB_Node *y=x->fa->fa->rchild; 84 if(y->color==RED) 85 { 86 y->color=BLACK; 87 x->fa->color=BLACK; 88 x->fa->fa->color=RED; 89 x=x->fa->fa; 90 } 91 else if(x==x->fa->rchild) 92 { 93 x=x->fa; 94 RB_Left_Rotate(T,x); 95 } 96 else 97 { 98 x->fa->fa->color=RED; 99 x->fa->color=BLACK; 100 RB_Right_Rotate(T,x->fa->fa); 101 } 102 } 103 else 104 { 105 RB_Node *y=x->fa->fa->lchild; 106 if(y->color==RED) 107 { 108 y->color=BLACK; 109 x->fa->color=BLACK; 110 x->fa->fa->color=RED; 111 x=x->fa->fa; 112 } 113 else if(x==x->fa->lchild) 114 { 115 x=x->fa; 116 RB_Right_Rotate(T,x); 117 } 118 else 119 { 120 x->fa->fa->color=RED; 121 x->fa->color=BLACK; 122 RB_Left_Rotate(T,x->fa->fa); 123 } 124 } 125 } 126 T->root->color=BLACK; 127 } 128 129 void RB_Insert(Tree *T,RB_Node *x) 130 { 131 //新插入结点显红色,可以在函数外面写 132 RB_Node *p=T->root,*q; 133 if(p==T->null) 134 { 135 T->root=x; 136 x->color=BLACK; 137 return ; 138 } 139 while(p!=T->null) 140 { 141 q=p; 142 if(x->data>=p->data) p=p->rchild; 143 else p=p->lchild; 144 } 145 if(x->data>=q->data) q->rchild=x; 146 else q->lchild=x; 147 x->fa=q; 148 RB_Adjust_Insert(T,x); 149 } 150 151 RB_Node *RB_Search_MinMum(Tree *T,RB_Node *x) 152 { 153 while(x->lchild!=T->null) 154 { 155 x=x->lchild; 156 } 157 return x; 158 } 159 160 void RB_Transplant(Tree *T,RB_Node *u,RB_Node *v) 161 { 162 if(u->fa==T->null) T->root=v; 163 else if(u->fa->lchild==u) u->fa->lchild=v; 164 else u->fa->rchild=v; 165 v->fa=u->fa; 166 } 167 168 void RB_Adjust_Delete(Tree *T,RB_Node *x) 169 { 170 while(x!=T->root&&x->color==BLACK) 171 { 172 if(x==x->fa->lchild) 173 { 174 RB_Node *w=x->fa->rchild; 175 if(w->color==RED) 176 { 177 w->color=BLACK; 178 x->fa->color=RED; 179 RB_Left_Rotate(T,x->fa); 180 w=x->fa->rchild; 181 } 182 else if(w->lchild->color==BLACK&&w->rchild->color==BLACK) 183 { 184 w->color==RED; 185 x=x->fa; 186 } 187 else if(w->rchild->color==BLACK) 188 { 189 w->lchild->color=BLACK; 190 w->color=RED; 191 RB_Right_Rotate(T,w); 192 w=x->fa->rchild; 193 } 194 else 195 { 196 w->color=x->fa->color; 197 x->fa->color=BLACK; 198 w->rchild->color=BLACK; 199 RB_Left_Rotate(T,x->fa); 200 x=T->root; 201 } 202 } 203 else 204 { 205 RB_Node *w=x->fa->lchild; 206 if(w->color==RED) 207 { 208 w->color=BLACK; 209 x->fa->color=RED; 210 RB_Right_Rotate(T,x->fa); 211 w=x->fa->lchild; 212 } 213 else if(w->lchild->color==BLACK&&w->rchild->color==BLACK) 214 { 215 w->color=RED; 216 x=x->fa; 217 } 218 else if(w->lchild->color==BLACK) 219 { 220 w->rchild->color=BLACK; 221 w->color=RED; 222 RB_Left_Rotate(T,w); 223 w=x->fa->lchild; 224 } 225 else 226 { 227 w->color=x->fa->color; 228 x->fa->color=BLACK; 229 w->lchild->color=BLACK; 230 RB_Right_Rotate(T,x->fa); 231 x=T->root; 232 } 233 } 234 } 235 x->color=BLACK; 236 } 237 238 void RB_Delete(Tree *T,RB_Node *z) 239 { 240 RB_Node *y=z,*x; 241 bool y_original_color=y->color; 242 if(z->lchild==T->null) 243 { 244 x=z->rchild; 245 RB_Transplant(T,z,z->rchild); 246 free(z); 247 } 248 else if(z->rchild==T->null) 249 { 250 x=z->lchild; 251 RB_Transplant(T,z,z->lchild); 252 free(z); 253 } 254 else 255 { 256 y=RB_Search_MinMum(T,z->rchild); 257 y_original_color=y->color; 258 x=y->rchild; 259 if(y->fa==z) 260 x->fa=y; //等会要从x处开始调整,如果x为T->null,那么现在先预置T->null的父结点为y 261 else 262 { 263 RB_Transplant(T,y,y->rchild); 264 y->rchild=z->rchild; 265 y->rchild->fa=y; //也有上面x->fa=y;的效果 266 } 267 RB_Transplant(T,z,y); 268 y->lchild=z->lchild; 269 y->lchild->fa=y; 270 y->color=z->color; 271 free(z); 272 } 273 if(y_original_color==BLACK) 274 RB_Adjust_Delete(T,x); 275 } 276 277 void RB_Display_Tree(Tree *T,RB_Node *p,int floor=0) 278 { 279 if(p==T->null) return; 280 RB_Display_Tree(T,p->lchild,floor+1); 281 for(int i=0;i<floor;i++) 282 printf(" "); 283 printf("%d %s\n",p->data,p->color==BLACK?"BLACK":"RED"); 284 RB_Display_Tree(T,p->rchild,floor+1); 285 } 286 287 RB_Node *RB_Search(Tree *T,int data) //找到第一个,如果没有,返回T->null 288 { 289 RB_Node *p=T->root; 290 while(p!=T->null) 291 { 292 if(p->data==data) return p; 293 if(data>p->data) p=p->rchild; 294 else p=p->lchild; 295 } 296 return T->null; 297 } 298 299 void RB_Clear(Tree *T,RB_Node *x) 300 { 301 if(x!=T->null) 302 { 303 RB_Clear(T,x->lchild); 304 RB_Clear(T,x->rchild); 305 free(x); 306 } 307 } 308 309 void CE_SHI() //用于测试红黑树 310 { 311 Tree *T; 312 T=Tree_Init(); 313 while(1) 314 { 315 printf("\n--------红黑树---------------\n"); 316 printf("1. 添加结点\n"); 317 printf("2. 删除结点\n"); 318 printf("0. 退出\n"); 319 int ch; 320 scanf("%d",&ch); 321 if(ch==1) 322 { 323 printf("请输入关键字:"); 324 scanf("%d",&ch); 325 RB_Node *x; 326 x=Node_Init(T); 327 x->data=ch; 328 RB_Insert(T,x); 329 RB_Display_Tree(T,T->root); 330 } 331 else if(ch==2) 332 { 333 printf("请输入关键字:"); 334 scanf("%d",&ch); 335 RB_Node *x=RB_Search(T,ch); 336 RB_Delete(T,x); 337 RB_Display_Tree(T,T->root); 338 } 339 else if(ch==0) 340 { 341 RB_Clear(T,T->root); 342 T->root=T->null; 343 } 344 system("pause"); 345 system("cls"); 346 RB_Display_Tree(T,T->root); 347 } 348 free(T); 349 } 350 351 int main() 352 { 353 CE_SHI(); 354 return 0; 355 }