码迷,mamicode.com
首页 > 其他好文 > 详细

红黑树入门

时间:2015-11-28 23:13:33      阅读:347      评论:0      收藏:0      [点我收藏+]

标签:

    红黑树 (参看《算法导论》)

  红黑树是一种平衡二叉树,巧妙地利用结点颜色来简化维护平衡的难度。具有如下性质:

  1.红黑树上所有结点要么是红色的,要么是黑色的。

  2.红黑树的根节点是黑色的。

  3.如果一个结点是红色的,那么他的两个子结点必须是黑色的。

  4.对于每一个结点,他左子树的黑色结点数量必然等于右子树的黑色结点数量。

  5.所有叶子结点必然是黑色的。

  (一)抛弃原有的NULL,所有指向NULL的指针,改为指向一个与普通结点相同的T.null结点,T.null结点颜色固定为黑色,这样便解决了叶子结点的问题,同时根结点的父指针也指向它。

  (二)每次新插入结点为红色,这样不影响性质1、4、5,也就是说当插入结点时,只可能影响到性质2或者3,维护起来方便,可以向上维护,(插入结点设为x),如果x为根结点,那么可以直接改成黑色,如果不是,那么判断父结点是不是红色,如果是,说明违背了性质4,可以通过旋转、上升矛盾(直至根)来解决。

  (三)删除一个结点,寻找替代的结点,也就是后继,将这个替代点改成与原要删除的点一样的颜色,这么,问题就缩小到替代点原位置可能少了一个黑结点,那么可以通过上升矛盾子树(即令与他相对应的兄弟子树也少一个黑结点,那么便变成父结点所在的子树少了一个黑结点)或者红转黑来解决,需要注意的是不要在维护过程中,违背更多的红黑树性质。

  

  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 }

 

红黑树入门

标签:

原文地址:http://www.cnblogs.com/hchlqlz-oj-mrj/p/5003603.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!