]> wimlib.net Git - wimlib/blob - src/rbtree.c
Win32 apply
[wimlib] / src / rbtree.c
1 /*
2   Red Black Trees
3   (C) 1999  Andrea Arcangeli <andrea@suse.de>
4   (C) 2002  David Woodhouse <dwmw2@infradead.org>
5   (C) 2012  Michel Lespinasse <walken@google.com>
6
7   This program is free software; you can redistribute it and/or modify
8   it under the terms of the GNU General Public License as published by
9   the Free Software Foundation; either version 2 of the License, or
10   (at your option) any later version.
11
12   This program is distributed in the hope that it will be useful,
13   but WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   GNU General Public License for more details.
16
17   You should have received a copy of the GNU General Public License
18   along with this program; if not, write to the Free Software
19   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20
21   linux/lib/rbtree.c
22 */
23
24 #include "rbtree.h"
25
26 /*
27  * red-black trees properties:  http://en.wikipedia.org/wiki/Rbtree
28  *
29  *  1) A node is either red or black
30  *  2) The root is black
31  *  3) All leaves (NULL) are black
32  *  4) Both children of every red node are black
33  *  5) Every simple path from root to leaves contains the same number
34  *     of black nodes.
35  *
36  *  4 and 5 give the O(log n) guarantee, since 4 implies you cannot have two
37  *  consecutive red nodes in a path and every red node is therefore followed by
38  *  a black. So if B is the number of black nodes on every simple path (as per
39  *  5), then the longest possible path due to 4 is 2B.
40  *
41  *  We shall indicate color with case, where black nodes are uppercase and red
42  *  nodes will be lowercase. Unknown color nodes shall be drawn as red within
43  *  parentheses and have some accompanying text comment.
44  */
45
46 struct rb_augment_callbacks {
47         void (*propagate)(struct rb_node *node, struct rb_node *stop);
48         void (*copy)(struct rb_node *old, struct rb_node *new);
49         void (*rotate)(struct rb_node *old, struct rb_node *new);
50 };
51
52 #define RB_RED          0
53 #define RB_BLACK        1
54
55 #define __rb_parent(pc)    ((struct rb_node *)(pc & ~3))
56
57 #define __rb_color(pc)     ((pc) & 1)
58 #define __rb_is_black(pc)  __rb_color(pc)
59 #define __rb_is_red(pc)    (!__rb_color(pc))
60 #define rb_color(rb)       __rb_color((rb)->__rb_parent_color)
61 #define rb_is_red(rb)      __rb_is_red((rb)->__rb_parent_color)
62 #define rb_is_black(rb)    __rb_is_black((rb)->__rb_parent_color)
63
64 static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p)
65 {
66         rb->__rb_parent_color = rb_color(rb) | (unsigned long)p;
67 }
68
69 static inline void rb_set_parent_color(struct rb_node *rb,
70                                        struct rb_node *p, int color)
71 {
72         rb->__rb_parent_color = (unsigned long)p | color;
73 }
74
75 static inline void rb_set_black(struct rb_node *rb)
76 {
77         rb->__rb_parent_color |= RB_BLACK;
78 }
79
80 static inline struct rb_node *rb_red_parent(struct rb_node *red)
81 {
82         return (struct rb_node *)red->__rb_parent_color;
83 }
84
85 static inline void
86 __rb_change_child(struct rb_node *old, struct rb_node *new,
87                   struct rb_node *parent, struct rb_root *root)
88 {
89         if (parent) {
90                 if (parent->rb_left == old)
91                         parent->rb_left = new;
92                 else
93                         parent->rb_right = new;
94         } else
95                 root->rb_node = new;
96 }
97
98 /*
99  * Helper function for rotations:
100  * - old's parent and color get assigned to new
101  * - old gets assigned new as a parent and 'color' as a color.
102  */
103 static inline void
104 __rb_rotate_set_parents(struct rb_node *old, struct rb_node *new,
105                         struct rb_root *root, int color)
106 {
107         struct rb_node *parent = rb_parent(old);
108         new->__rb_parent_color = old->__rb_parent_color;
109         rb_set_parent_color(old, new, color);
110         __rb_change_child(old, new, parent, root);
111 }
112
113 static inline void
114 __rb_erase_color(struct rb_node *parent, struct rb_root *root,
115         void (*augment_rotate)(struct rb_node *old, struct rb_node *new))
116 {
117         struct rb_node *node = NULL, *sibling, *tmp1, *tmp2;
118
119         while (true) {
120                 /*
121                  * Loop invariants:
122                  * - node is black (or NULL on first iteration)
123                  * - node is not the root (parent is not NULL)
124                  * - All leaf paths going through parent and node have a
125                  *   black node count that is 1 lower than other leaf paths.
126                  */
127                 sibling = parent->rb_right;
128                 if (node != sibling) {  /* node == parent->rb_left */
129                         if (rb_is_red(sibling)) {
130                                 /*
131                                  * Case 1 - left rotate at parent
132                                  *
133                                  *     P               S
134                                  *    / \             / \
135                                  *   N   s    -->    p   Sr
136                                  *      / \         / \
137                                  *     Sl  Sr      N   Sl
138                                  */
139                                 parent->rb_right = tmp1 = sibling->rb_left;
140                                 sibling->rb_left = parent;
141                                 rb_set_parent_color(tmp1, parent, RB_BLACK);
142                                 __rb_rotate_set_parents(parent, sibling, root,
143                                                         RB_RED);
144                                 augment_rotate(parent, sibling);
145                                 sibling = tmp1;
146                         }
147                         tmp1 = sibling->rb_right;
148                         if (!tmp1 || rb_is_black(tmp1)) {
149                                 tmp2 = sibling->rb_left;
150                                 if (!tmp2 || rb_is_black(tmp2)) {
151                                         /*
152                                          * Case 2 - sibling color flip
153                                          * (p could be either color here)
154                                          *
155                                          *    (p)           (p)
156                                          *    / \           / \
157                                          *   N   S    -->  N   s
158                                          *      / \           / \
159                                          *     Sl  Sr        Sl  Sr
160                                          *
161                                          * This leaves us violating 5) which
162                                          * can be fixed by flipping p to black
163                                          * if it was red, or by recursing at p.
164                                          * p is red when coming from Case 1.
165                                          */
166                                         rb_set_parent_color(sibling, parent,
167                                                             RB_RED);
168                                         if (rb_is_red(parent))
169                                                 rb_set_black(parent);
170                                         else {
171                                                 node = parent;
172                                                 parent = rb_parent(node);
173                                                 if (parent)
174                                                         continue;
175                                         }
176                                         break;
177                                 }
178                                 /*
179                                  * Case 3 - right rotate at sibling
180                                  * (p could be either color here)
181                                  *
182                                  *   (p)           (p)
183                                  *   / \           / \
184                                  *  N   S    -->  N   Sl
185                                  *     / \             \
186                                  *    sl  Sr            s
187                                  *                       \
188                                  *                        Sr
189                                  */
190                                 sibling->rb_left = tmp1 = tmp2->rb_right;
191                                 tmp2->rb_right = sibling;
192                                 parent->rb_right = tmp2;
193                                 if (tmp1)
194                                         rb_set_parent_color(tmp1, sibling,
195                                                             RB_BLACK);
196                                 augment_rotate(sibling, tmp2);
197                                 tmp1 = sibling;
198                                 sibling = tmp2;
199                         }
200                         /*
201                          * Case 4 - left rotate at parent + color flips
202                          * (p and sl could be either color here.
203                          *  After rotation, p becomes black, s acquires
204                          *  p's color, and sl keeps its color)
205                          *
206                          *      (p)             (s)
207                          *      / \             / \
208                          *     N   S     -->   P   Sr
209                          *        / \         / \
210                          *      (sl) sr      N  (sl)
211                          */
212                         parent->rb_right = tmp2 = sibling->rb_left;
213                         sibling->rb_left = parent;
214                         rb_set_parent_color(tmp1, sibling, RB_BLACK);
215                         if (tmp2)
216                                 rb_set_parent(tmp2, parent);
217                         __rb_rotate_set_parents(parent, sibling, root,
218                                                 RB_BLACK);
219                         augment_rotate(parent, sibling);
220                         break;
221                 } else {
222                         sibling = parent->rb_left;
223                         if (rb_is_red(sibling)) {
224                                 /* Case 1 - right rotate at parent */
225                                 parent->rb_left = tmp1 = sibling->rb_right;
226                                 sibling->rb_right = parent;
227                                 rb_set_parent_color(tmp1, parent, RB_BLACK);
228                                 __rb_rotate_set_parents(parent, sibling, root,
229                                                         RB_RED);
230                                 augment_rotate(parent, sibling);
231                                 sibling = tmp1;
232                         }
233                         tmp1 = sibling->rb_left;
234                         if (!tmp1 || rb_is_black(tmp1)) {
235                                 tmp2 = sibling->rb_right;
236                                 if (!tmp2 || rb_is_black(tmp2)) {
237                                         /* Case 2 - sibling color flip */
238                                         rb_set_parent_color(sibling, parent,
239                                                             RB_RED);
240                                         if (rb_is_red(parent))
241                                                 rb_set_black(parent);
242                                         else {
243                                                 node = parent;
244                                                 parent = rb_parent(node);
245                                                 if (parent)
246                                                         continue;
247                                         }
248                                         break;
249                                 }
250                                 /* Case 3 - right rotate at sibling */
251                                 sibling->rb_right = tmp1 = tmp2->rb_left;
252                                 tmp2->rb_left = sibling;
253                                 parent->rb_left = tmp2;
254                                 if (tmp1)
255                                         rb_set_parent_color(tmp1, sibling,
256                                                             RB_BLACK);
257                                 augment_rotate(sibling, tmp2);
258                                 tmp1 = sibling;
259                                 sibling = tmp2;
260                         }
261                         /* Case 4 - left rotate at parent + color flips */
262                         parent->rb_left = tmp2 = sibling->rb_right;
263                         sibling->rb_right = parent;
264                         rb_set_parent_color(tmp1, sibling, RB_BLACK);
265                         if (tmp2)
266                                 rb_set_parent(tmp2, parent);
267                         __rb_rotate_set_parents(parent, sibling, root,
268                                                 RB_BLACK);
269                         augment_rotate(parent, sibling);
270                         break;
271                 }
272         }
273 }
274
275 static inline void
276 rb_erase_augmented(struct rb_node *node, struct rb_root *root,
277                    const struct rb_augment_callbacks *augment)
278 {
279         struct rb_node *child = node->rb_right, *tmp = node->rb_left;
280         struct rb_node *parent, *rebalance;
281         unsigned long pc;
282
283         if (!tmp) {
284                 /*
285                  * Case 1: node to erase has no more than 1 child (easy!)
286                  *
287                  * Note that if there is one child it must be red due to 5)
288                  * and node must be black due to 4). We adjust colors locally
289                  * so as to bypass __rb_erase_color() later on.
290                  */
291                 pc = node->__rb_parent_color;
292                 parent = __rb_parent(pc);
293                 __rb_change_child(node, child, parent, root);
294                 if (child) {
295                         child->__rb_parent_color = pc;
296                         rebalance = NULL;
297                 } else
298                         rebalance = __rb_is_black(pc) ? parent : NULL;
299                 tmp = parent;
300         } else if (!child) {
301                 /* Still case 1, but this time the child is node->rb_left */
302                 tmp->__rb_parent_color = pc = node->__rb_parent_color;
303                 parent = __rb_parent(pc);
304                 __rb_change_child(node, tmp, parent, root);
305                 rebalance = NULL;
306                 tmp = parent;
307         } else {
308                 struct rb_node *successor = child, *child2;
309                 tmp = child->rb_left;
310                 if (!tmp) {
311                         /*
312                          * Case 2: node's successor is its right child
313                          *
314                          *    (n)          (s)
315                          *    / \          / \
316                          *  (x) (s)  ->  (x) (c)
317                          *        \
318                          *        (c)
319                          */
320                         parent = successor;
321                         child2 = successor->rb_right;
322                         augment->copy(node, successor);
323                 } else {
324                         /*
325                          * Case 3: node's successor is leftmost under
326                          * node's right child subtree
327                          *
328                          *    (n)          (s)
329                          *    / \          / \
330                          *  (x) (y)  ->  (x) (y)
331                          *      /            /
332                          *    (p)          (p)
333                          *    /            /
334                          *  (s)          (c)
335                          *    \
336                          *    (c)
337                          */
338                         do {
339                                 parent = successor;
340                                 successor = tmp;
341                                 tmp = tmp->rb_left;
342                         } while (tmp);
343                         parent->rb_left = child2 = successor->rb_right;
344                         successor->rb_right = child;
345                         rb_set_parent(child, successor);
346                         augment->copy(node, successor);
347                         augment->propagate(parent, successor);
348                 }
349
350                 successor->rb_left = tmp = node->rb_left;
351                 rb_set_parent(tmp, successor);
352
353                 pc = node->__rb_parent_color;
354                 tmp = __rb_parent(pc);
355                 __rb_change_child(node, successor, tmp, root);
356                 if (child2) {
357                         successor->__rb_parent_color = pc;
358                         rb_set_parent_color(child2, parent, RB_BLACK);
359                         rebalance = NULL;
360                 } else {
361                         unsigned long pc2 = successor->__rb_parent_color;
362                         successor->__rb_parent_color = pc;
363                         rebalance = __rb_is_black(pc2) ? parent : NULL;
364                 }
365                 tmp = successor;
366         }
367
368         augment->propagate(tmp, NULL);
369         if (rebalance)
370                 __rb_erase_color(rebalance, root, augment->rotate);
371 }
372
373
374 static inline void
375 __rb_insert(struct rb_node *node, struct rb_root *root,
376             void (*augment_rotate)(struct rb_node *old, struct rb_node *new))
377 {
378         struct rb_node *parent = rb_red_parent(node), *gparent, *tmp;
379
380         while (true) {
381                 /*
382                  * Loop invariant: node is red
383                  *
384                  * If there is a black parent, we are done.
385                  * Otherwise, take some corrective action as we don't
386                  * want a red root or two consecutive red nodes.
387                  */
388                 if (!parent) {
389                         rb_set_parent_color(node, NULL, RB_BLACK);
390                         break;
391                 } else if (rb_is_black(parent))
392                         break;
393
394                 gparent = rb_red_parent(parent);
395
396                 tmp = gparent->rb_right;
397                 if (parent != tmp) {    /* parent == gparent->rb_left */
398                         if (tmp && rb_is_red(tmp)) {
399                                 /*
400                                  * Case 1 - color flips
401                                  *
402                                  *       G            g
403                                  *      / \          / \
404                                  *     p   u  -->   P   U
405                                  *    /            /
406                                  *   n            N
407                                  *
408                                  * However, since g's parent might be red, and
409                                  * 4) does not allow this, we need to recurse
410                                  * at g.
411                                  */
412                                 rb_set_parent_color(tmp, gparent, RB_BLACK);
413                                 rb_set_parent_color(parent, gparent, RB_BLACK);
414                                 node = gparent;
415                                 parent = rb_parent(node);
416                                 rb_set_parent_color(node, parent, RB_RED);
417                                 continue;
418                         }
419
420                         tmp = parent->rb_right;
421                         if (node == tmp) {
422                                 /*
423                                  * Case 2 - left rotate at parent
424                                  *
425                                  *      G             G
426                                  *     / \           / \
427                                  *    p   U  -->    n   U
428                                  *     \           /
429                                  *      n         p
430                                  *
431                                  * This still leaves us in violation of 4), the
432                                  * continuation into Case 3 will fix that.
433                                  */
434                                 parent->rb_right = tmp = node->rb_left;
435                                 node->rb_left = parent;
436                                 if (tmp)
437                                         rb_set_parent_color(tmp, parent,
438                                                             RB_BLACK);
439                                 rb_set_parent_color(parent, node, RB_RED);
440                                 augment_rotate(parent, node);
441                                 parent = node;
442                                 tmp = node->rb_right;
443                         }
444
445                         /*
446                          * Case 3 - right rotate at gparent
447                          *
448                          *        G           P
449                          *       / \         / \
450                          *      p   U  -->  n   g
451                          *     /                 \
452                          *    n                   U
453                          */
454                         gparent->rb_left = tmp;  /* == parent->rb_right */
455                         parent->rb_right = gparent;
456                         if (tmp)
457                                 rb_set_parent_color(tmp, gparent, RB_BLACK);
458                         __rb_rotate_set_parents(gparent, parent, root, RB_RED);
459                         augment_rotate(gparent, parent);
460                         break;
461                 } else {
462                         tmp = gparent->rb_left;
463                         if (tmp && rb_is_red(tmp)) {
464                                 /* Case 1 - color flips */
465                                 rb_set_parent_color(tmp, gparent, RB_BLACK);
466                                 rb_set_parent_color(parent, gparent, RB_BLACK);
467                                 node = gparent;
468                                 parent = rb_parent(node);
469                                 rb_set_parent_color(node, parent, RB_RED);
470                                 continue;
471                         }
472
473                         tmp = parent->rb_left;
474                         if (node == tmp) {
475                                 /* Case 2 - right rotate at parent */
476                                 parent->rb_left = tmp = node->rb_right;
477                                 node->rb_right = parent;
478                                 if (tmp)
479                                         rb_set_parent_color(tmp, parent,
480                                                             RB_BLACK);
481                                 rb_set_parent_color(parent, node, RB_RED);
482                                 augment_rotate(parent, node);
483                                 parent = node;
484                                 tmp = node->rb_left;
485                         }
486
487                         /* Case 3 - left rotate at gparent */
488                         gparent->rb_right = tmp;  /* == parent->rb_left */
489                         parent->rb_left = gparent;
490                         if (tmp)
491                                 rb_set_parent_color(tmp, gparent, RB_BLACK);
492                         __rb_rotate_set_parents(gparent, parent, root, RB_RED);
493                         augment_rotate(gparent, parent);
494                         break;
495                 }
496         }
497 }
498
499
500 /*
501  * Non-augmented rbtree manipulation functions.
502  *
503  * We use dummy augmented callbacks here, and have the compiler optimize them
504  * out of the rb_insert_color() and rb_erase() function definitions.
505  */
506
507 static inline void dummy_propagate(struct rb_node *node, struct rb_node *stop) {}
508 static inline void dummy_copy(struct rb_node *old, struct rb_node *new) {}
509 static inline void dummy_rotate(struct rb_node *old, struct rb_node *new) {}
510
511 static const struct rb_augment_callbacks dummy_callbacks = {
512         dummy_propagate, dummy_copy, dummy_rotate
513 };
514
515 void rb_insert_color(struct rb_node *node, struct rb_root *root)
516 {
517         __rb_insert(node, root, dummy_rotate);
518 }
519
520 void rb_erase(struct rb_node *node, struct rb_root *root)
521 {
522         rb_erase_augmented(node, root, &dummy_callbacks);
523 }