1 /*-----------------------------------------------------------
2 RB-Tree的插入和删除操作的实现算法
3 参考资料:
4 1) <<Introduction to algorithm>>
5 2) [url]http://lxr.linux.no/linux/lib/rbtree.c[/url]
6 作者:[url]http://www.cppblog.com/converse/[/url]
7 您可以自由的传播,修改这份代码,转载处请注明原作者
8 红黑树的几个性质:
9 1) 每个结点只有红和黑两种颜色
10 2) 根结点是黑色的
11 3)空节点是黑色的(红黑树中,根节点的parent以及所有叶节点lchild、rchild都不指向NULL,而是指向一个定义好的
12 空节点)。
13 4) 如果一个结点是红色的,那么它的左右两个子结点的颜色是黑色的
14 5) 对于每个结点而言,从这个结点到叶子结点的任何路径上的黑色结点
15 的数目相同
16 -------------------------------------------------------------*/
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 typedef enum color_t
21 {
22 RED = 0,
23 BLACK = 1
24 }color_t;
25 typedef struct rb_node_t
26 {
27 struct rb_node_t *left, *right, *parent;
28 char key[21];
29 color_t color;
30 }rb_node_t;
31
32 /* forward declaration */
33 rb_node_t* rb_insert(char * key, rb_node_t* root);
34 rb_node_t* rb_search(char * key, rb_node_t* root);
35 rb_node_t* rb_erase(char * key, rb_node_t* root);
36 static rb_node_t* rb_new_node(char * key)
37 {
38 rb_node_t *node = (rb_node_t*)malloc(sizeof(struct rb_node_t));
39 if (!node)
40 {
41 printf("malloc error!\n");
42 exit(-1);
43 }
44 strcpy(node->key,key);
45 return node;
46 }
47 /*-----------------------------------------------------------
48 | node right
49 | / \ ==> / \
50 | a right node y
51 | / \ / \
52 | b y a b
53 -----------------------------------------------------------*/
54 static rb_node_t* rb_rotate_left(rb_node_t* node, rb_node_t* root)
55 {
56 rb_node_t* right = node->right;
57 if ((node->right = right->left))
58 {
59 right->left->parent = node;
60 }
61 right->left = node;
62 if ((right->parent = node->parent))
63 {
64 if (node == node->parent->right)
65 {
66 node->parent->right = right;
67 }
68 else
69 {
70 node->parent->left = right;
71 }
72 }
73 else
74 {
75 root = right;
76 }
77 node->parent = right;
78 return root;
79 }
80 /*-----------------------------------------------------------
81 | node left
82 | / \ / \
83 | left y ==> a node
84 | / \ / \
85 | a b b y
86 -----------------------------------------------------------*/
87 static rb_node_t* rb_rotate_right(rb_node_t* node, rb_node_t* root)
88 {
89 rb_node_t* left = node->left;
90 if ((node->left = left->right))
91 {
92 left->right->parent = node;
93 }
94 left->right = node;
95 if ((left->parent = node->parent))
96 {
97 if (node == node->parent->right)
98 {
99 node->parent->right = left;
100 }
101 else
102 {
103 node->parent->left = left;
104 }
105 }
106 else
107 {
108 root = left;
109 }
110 node->parent = left;
111 return root;
112 }
113 static rb_node_t* rb_insert_rebalance(rb_node_t *node, rb_node_t *root)
114 {
115 rb_node_t *parent, *gparent, *uncle, *tmp;
116 while ((parent = node->parent) && parent->color == RED)
117 {
118 gparent = parent->parent;
119 if (parent == gparent->left)
120 {
121 uncle = gparent->right;
122 if (uncle && uncle->color == RED)
123 {
124 uncle->color = BLACK;
125 parent->color = BLACK;
126 gparent->color = RED;
127 node = gparent;
128 }
129 else
130 {
131 if (parent->right == node)
132 {
133 root = rb_rotate_left(parent, root);
134 tmp = parent;
135 parent = node;
136 node = tmp;
137 }
138 parent->color = BLACK;
139 gparent->color = RED;
140 root = rb_rotate_right(gparent, root);
141 }
142 }
143 else
144 {
145 uncle = gparent->left;
146 if (uncle && uncle->color == RED)
147 {
148 uncle->color = BLACK;
149 parent->color = BLACK;
150 gparent->color = RED;
151 node = gparent;
152 }
153 else
154 {
155 if (parent->left == node)
156 {
157 root = rb_rotate_right(parent, root);
158 tmp = parent;
159 parent = node;
160 node = tmp;
161 }
162 parent->color = BLACK;
163 gparent->color = RED;
164 root = rb_rotate_left(gparent, root);
165 }
166 }
167 }
168 root->color = BLACK;
169 return root;
170 }
171 static rb_node_t* rb_erase_rebalance(rb_node_t *node, rb_node_t *parent, rb_node_t *root)
172 {
173 rb_node_t *other, *o_left, *o_right;
174 while ((!node || node->color == BLACK) && node != root)
175 {
176 if (parent->left == node)
177 {
178 other = parent->right;
179 if (other->color == RED)
180 {
181 other->color = BLACK;
182 parent->color = RED;
183 root = rb_rotate_left(parent, root);
184 other = parent->right;
185 }
186 if ((!other->left || other->left->color == BLACK) &&
187 (!other->right || other->right->color == BLACK))
188 {
189 other->color = RED;
190 node = parent;
191 parent = node->parent;
192 }
193 else
194 {
195 if (!other->right || other->right->color == BLACK)
196 {
197 if ((o_left = other->left))
198 {
199 o_left->color = BLACK;
200 }
201 other->color = RED;
202 root = rb_rotate_right(other, root);
203 other = parent->right;
204 }
205 other->color = parent->color;
206 parent->color = BLACK;
207 if (other->right)
208 {
209 other->right->color = BLACK;
210 }
211 root = rb_rotate_left(parent, root);
212 node = root;
213 break;
214 }
215 }
216 else
217 {
218 other = parent->left;
219 if (other->color == RED)
220 {
221 other->color = BLACK;
222 parent->color = RED;
223 root = rb_rotate_right(parent, root);
224 other = parent->left;
225 }
226 if ((!other->left || other->left->color == BLACK) &&
227 (!other->right || other->right->color == BLACK))
228 {
229 other->color = RED;
230 node = parent;
231 parent = node->parent;
232 }
233 else
234 {
235 if (!other->left || other->left->color == BLACK)
236 {
237 if ((o_right = other->right))
238 {
239 o_right->color = BLACK;
240 }
241 other->color = RED;
242 root = rb_rotate_left(other, root);
243 other = parent->left;
244 }
245 other->color = parent->color;
246 parent->color = BLACK;
247 if (other->left)
248 {
249 other->left->color = BLACK;
250 }
251 root = rb_rotate_right(parent, root);
252 node = root;
253 break;
254 }
255 }
256 }
257 if (node)
258 {
259 node->color = BLACK;
260 }
261 return root;
262 }
263 static rb_node_t* rb_search_auxiliary(char * key, rb_node_t* root, rb_node_t** save)
264 {
265 rb_node_t *node = root, *parent = NULL;
266 int ret;
267 while (node)
268 {
269 parent = node;
270 ret = strcmp(node->key,key);
271 if (0 < ret)
272 {
273 node = node->left;
274 }
275 else if (0 > ret)
276 {
277 node = node->right;
278 }
279 else
280 {
281 return node;
282 }
283 }
284 if (save)
285 {
286 *save = parent;
287 }
288 return NULL;
289 }
290 rb_node_t* rb_insert(char * key,rb_node_t* root)
291 {
292 rb_node_t *parent = NULL, *node;
293 parent = NULL;
294 if ((node = rb_search_auxiliary(key, root, &parent)))
295 {
296 return root;
297 }
298 node = rb_new_node(key);
299 node->parent = parent;
300 node->left = node->right = NULL;
301 node->color = RED;
302 if (parent)
303 {
304 if (strcmp(parent->key,key) > 0)
305 {
306 parent->left = node;
307 }
308 else
309 {
310 parent->right = node;
311 }
312 }
313 else
314 {
315 root = node;
316 }
317 return rb_insert_rebalance(node, root);
318 }
319 rb_node_t* rb_search(char * key, rb_node_t* root)
320 {
321 return rb_search_auxiliary(key, root, NULL);
322 }
323 rb_node_t* rb_erase(char * key, rb_node_t *root)
324 {
325 rb_node_t *child, *parent, *old, *left, *node;
326 color_t color;
327 if (!(node = rb_search_auxiliary(key, root, NULL)))
328 {
329 printf("key %d is not exist!\n");
330 return root;
331 }
332 old = node;
333 if (node->left && node->right)
334 {
335 node = node->right;
336 while ((left = node->left) != NULL)
337 {
338 node = left;
339 }
340 child = node->right;
341 parent = node->parent;
342 color = node->color;
343 if (child)
344 {
345 child->parent = parent;
346 }
347 if (parent)
348 {
349 if (parent->left == node)
350 {
351 parent->left = child;
352 }
353 else
354 {
355 parent->right = child;
356 }
357 }
358 else
359 {
360 root = child;
361 }
362 if (node->parent == old)
363 {
364 parent = node;
365 }
366 node->parent = old->parent;
367 node->color = old->color;
368 node->right = old->right;
369 node->left = old->left;
370 if (old->parent)
371 {
372 if (old->parent->left == old)
373 {
374 old->parent->left = node;
375 }
376 else
377 {
378 old->parent->right = node;
379 }
380 }
381 else
382 {
383 root = node;
384 }
385 old->left->parent = node;
386 if (old->right)
387 {
388 old->right->parent = node;
389 }
390 }
391 else
392 {
393 if (!node->left)
394 {
395 child = node->right;
396 }
397 else if (!node->right)
398 {
399 child = node->left;
400 }
401 parent = node->parent;
402 color = node->color;
403 if (child)
404 {
405 child->parent = parent;
406 }
407 if (parent)
408 {
409 if (parent->left == node)
410 {
411 parent->left = child;
412 }
413 else
414 {
415 parent->right = child;
416 }
417 }
418 else
419 {
420 root = child;
421 }
422 }
423 free(old);
424 if (color == BLACK)
425 {
426 root = rb_erase_rebalance(child, parent, root);
427 }
428 return root;
429 }