nfs-ganesha 1.4
|
00001 /* 00002 * rbtree - Implements a red-black tree with parent pointers. 00003 * 00004 * Copyright (C) 2010 Franck Bui-Huu <fbuihuu@gmail.com> 00005 * 00006 * This library is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU Lesser General Public License 00008 * as published by the Free Software Foundation; version 2 of the 00009 * License. 00010 * 00011 * This library is distributed in the hope that it will be useful, but 00012 * WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public 00017 * License along with this library; if not, write to the Free Software 00018 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 00019 * USA 00020 */ 00021 00022 /* 00023 * For recall a red-black tree has the following properties: 00024 * 00025 * 1. All nodes are either BLACK or RED 00026 * 2. Leafs are BLACK 00027 * 3. A RED node has BLACK children only 00028 * 4. Path from a node to any leafs has the same number of BLACK nodes. 00029 * 00030 */ 00031 #ifdef HAVE_CONFIG_H 00032 #include "config.h" 00033 #endif 00034 #include "avltree.h" 00035 00036 /* 00037 * Some helpers 00038 */ 00039 #ifdef UINTPTR_MAX 00040 00041 static inline enum rb_color get_color(const struct rbtree_node *node) 00042 { 00043 return node->parent & 1; 00044 } 00045 00046 static inline void set_color(enum rb_color color, struct rbtree_node *node) 00047 { 00048 node->parent = (node->parent & ~1UL) | color; 00049 } 00050 00051 static inline struct rbtree_node *get_parent(const struct rbtree_node *node) 00052 { 00053 return (struct rbtree_node *)(node->parent & ~1UL); 00054 } 00055 00056 static inline void set_parent(struct rbtree_node *parent, struct rbtree_node *node) 00057 { 00058 node->parent = (uintptr_t)parent | (node->parent & 1); 00059 } 00060 00061 #else 00062 00063 static inline enum rb_color get_color(const struct rbtree_node *node) 00064 { 00065 return node->color; 00066 } 00067 00068 static inline void set_color(enum rb_color color, struct rbtree_node *node) 00069 { 00070 node->color = color; 00071 } 00072 00073 static inline struct rbtree_node *get_parent(const struct rbtree_node *node) 00074 { 00075 return node->parent; 00076 } 00077 00078 static inline void set_parent(struct rbtree_node *parent, struct rbtree_node *node) 00079 { 00080 node->parent = parent; 00081 } 00082 00083 #endif /* UINTPTR_MAX */ 00084 00085 static inline int is_root(struct rbtree_node *node) 00086 { 00087 return get_parent(node) == NULL; 00088 } 00089 00090 static inline int is_black(struct rbtree_node *node) 00091 { 00092 return get_color(node) == RB_BLACK; 00093 } 00094 00095 static inline int is_red(struct rbtree_node *node) 00096 { 00097 return !is_black(node); 00098 } 00099 00100 /* 00101 * Iterators 00102 */ 00103 static inline struct rbtree_node *get_first(struct rbtree_node *node) 00104 { 00105 while (node->left) 00106 node = node->left; 00107 return node; 00108 } 00109 00110 static inline struct rbtree_node *get_last(struct rbtree_node *node) 00111 { 00112 while (node->right) 00113 node = node->right; 00114 return node; 00115 } 00116 00117 struct rbtree_node *rbtree_first(const struct rbtree *tree) 00118 { 00119 return tree->first; 00120 } 00121 00122 struct rbtree_node *rbtree_last(const struct rbtree *tree) 00123 { 00124 return tree->last; 00125 } 00126 00127 struct rbtree_node *rbtree_next(const struct rbtree_node *node) 00128 { 00129 struct rbtree_node *parent; 00130 00131 if (node->right) 00132 return get_first(node->right); 00133 00134 while ((parent = get_parent(node)) && parent->right == node) 00135 node = parent; 00136 return parent; 00137 } 00138 00139 struct rbtree_node *rbtree_prev(const struct rbtree_node *node) 00140 { 00141 struct rbtree_node *parent; 00142 00143 if (node->left) 00144 return get_last(node->left); 00145 00146 while ((parent = get_parent(node)) && parent->left == node) 00147 node = parent; 00148 return parent; 00149 } 00150 00151 /* 00152 * 'pparent' and 'is_left' are only used for insertions. Normally GCC 00153 * will notice this and get rid of them for lookups. 00154 */ 00155 static inline struct rbtree_node *do_lookup(const struct rbtree_node *key, 00156 const struct rbtree *tree, 00157 struct rbtree_node **pparent, 00158 int *is_left) 00159 { 00160 struct rbtree_node *node = tree->root; 00161 00162 *pparent = NULL; 00163 *is_left = 0; 00164 00165 while (node) { 00166 int res = tree->cmp_fn(node, key); 00167 if (res == 0) 00168 return node; 00169 *pparent = node; 00170 if ((*is_left = res > 0)) 00171 node = node->left; 00172 else 00173 node = node->right; 00174 } 00175 return NULL; 00176 } 00177 00178 /* 00179 * Rotate operations (They preserve the binary search tree property, 00180 * assuming that the keys are unique). 00181 */ 00182 static void rotate_left(struct rbtree_node *node, struct rbtree *tree) 00183 { 00184 struct rbtree_node *p = node; 00185 struct rbtree_node *q = node->right; /* can't be NULL */ 00186 struct rbtree_node *parent = get_parent(p); 00187 00188 if (!is_root(p)) { 00189 if (parent->left == p) 00190 parent->left = q; 00191 else 00192 parent->right = q; 00193 } else 00194 tree->root = q; 00195 set_parent(parent, q); 00196 set_parent(q, p); 00197 00198 p->right = q->left; 00199 if (p->right) 00200 set_parent(p, p->right); 00201 q->left = p; 00202 } 00203 00204 static void rotate_right(struct rbtree_node *node, struct rbtree *tree) 00205 { 00206 struct rbtree_node *p = node; 00207 struct rbtree_node *q = node->left; /* can't be NULL */ 00208 struct rbtree_node *parent = get_parent(p); 00209 00210 if (!is_root(p)) { 00211 if (parent->left == p) 00212 parent->left = q; 00213 else 00214 parent->right = q; 00215 } else 00216 tree->root = q; 00217 set_parent(parent, q); 00218 set_parent(q, p); 00219 00220 p->left = q->right; 00221 if (p->left) 00222 set_parent(p, p->left); 00223 q->right = p; 00224 } 00225 00226 struct rbtree_node *rbtree_lookup(const struct rbtree_node *key, 00227 const struct rbtree *tree) 00228 { 00229 struct rbtree_node *parent; 00230 int is_left; 00231 00232 return do_lookup(key, tree, &parent, &is_left); 00233 } 00234 00235 static void set_child(struct rbtree_node *child, struct rbtree_node *node, int left) 00236 { 00237 if (left) 00238 node->left = child; 00239 else 00240 node->right = child; 00241 } 00242 00243 struct rbtree_node *rbtree_insert(struct rbtree_node *node, struct rbtree *tree) 00244 { 00245 struct rbtree_node *key, *parent; 00246 int is_left; 00247 00248 key = do_lookup(node, tree, &parent, &is_left); 00249 if (key) 00250 return key; 00251 00252 node->left = NULL; 00253 node->right = NULL; 00254 set_color(RB_RED, node); 00255 set_parent(parent, node); 00256 00257 if (parent) { 00258 if (is_left) { 00259 if (parent == tree->first) 00260 tree->first = node; 00261 } else { 00262 if (parent == tree->last) 00263 tree->last = node; 00264 } 00265 set_child(node, parent, is_left); 00266 } else { 00267 tree->root = node; 00268 tree->first = node; 00269 tree->last = node; 00270 } 00271 00272 /* 00273 * Fixup the modified tree by recoloring nodes and performing 00274 * rotations (2 at most) hence the red-black tree properties are 00275 * preserved. 00276 */ 00277 while ((parent = get_parent(node)) && is_red(parent)) { 00278 struct rbtree_node *grandpa = get_parent(parent); 00279 00280 if (parent == grandpa->left) { 00281 struct rbtree_node *uncle = grandpa->right; 00282 00283 if (uncle && is_red(uncle)) { 00284 set_color(RB_BLACK, parent); 00285 set_color(RB_BLACK, uncle); 00286 set_color(RB_RED, grandpa); 00287 node = grandpa; 00288 } else { 00289 if (node == parent->right) { 00290 rotate_left(parent, tree); 00291 node = parent; 00292 parent = get_parent(node); 00293 } 00294 set_color(RB_BLACK, parent); 00295 set_color(RB_RED, grandpa); 00296 rotate_right(grandpa, tree); 00297 } 00298 } else { 00299 struct rbtree_node *uncle = grandpa->left; 00300 00301 if (uncle && is_red(uncle)) { 00302 set_color(RB_BLACK, parent); 00303 set_color(RB_BLACK, uncle); 00304 set_color(RB_RED, grandpa); 00305 node = grandpa; 00306 } else { 00307 if (node == parent->left) { 00308 rotate_right(parent, tree); 00309 node = parent; 00310 parent = get_parent(node); 00311 } 00312 set_color(RB_BLACK, parent); 00313 set_color(RB_RED, grandpa); 00314 rotate_left(grandpa, tree); 00315 } 00316 } 00317 } 00318 set_color(RB_BLACK, tree->root); 00319 return NULL; 00320 } 00321 00322 void rbtree_remove(struct rbtree_node *node, struct rbtree *tree) 00323 { 00324 struct rbtree_node *parent = get_parent(node); 00325 struct rbtree_node *left = node->left; 00326 struct rbtree_node *right = node->right; 00327 struct rbtree_node *next; 00328 enum rb_color color; 00329 00330 if (node == tree->first) 00331 tree->first = rbtree_next(node); 00332 if (node == tree->last) 00333 tree->last = rbtree_prev(node); 00334 00335 if (!left) 00336 next = right; 00337 else if (!right) 00338 next = left; 00339 else 00340 next = get_first(right); 00341 00342 if (parent) 00343 set_child(next, parent, parent->left == node); 00344 else 00345 tree->root = next; 00346 00347 if (left && right) { 00348 color = get_color(next); 00349 set_color(get_color(node), next); 00350 00351 next->left = left; 00352 set_parent(next, left); 00353 00354 if (next != right) { 00355 parent = get_parent(next); 00356 set_parent(get_parent(node), next); 00357 00358 node = next->right; 00359 parent->left = node; 00360 00361 next->right = right; 00362 set_parent(next, right); 00363 } else { 00364 set_parent(parent, next); 00365 parent = next; 00366 node = next->right; 00367 } 00368 } else { 00369 color = get_color(node); 00370 node = next; 00371 } 00372 /* 00373 * 'node' is now the sole successor's child and 'parent' its 00374 * new parent (since the successor can have been moved). 00375 */ 00376 if (node) 00377 set_parent(parent, node); 00378 00379 /* 00380 * The 'easy' cases. 00381 */ 00382 if (color == RB_RED) 00383 return; 00384 if (node && is_red(node)) { 00385 set_color(RB_BLACK, node); 00386 return; 00387 } 00388 00389 do { 00390 if (node == tree->root) 00391 break; 00392 00393 if (node == parent->left) { 00394 struct rbtree_node *sibling = parent->right; 00395 00396 if (is_red(sibling)) { 00397 set_color(RB_BLACK, sibling); 00398 set_color(RB_RED, parent); 00399 rotate_left(parent, tree); 00400 sibling = parent->right; 00401 } 00402 if ((!sibling->left || is_black(sibling->left)) && 00403 (!sibling->right || is_black(sibling->right))) { 00404 set_color(RB_RED, sibling); 00405 node = parent; 00406 parent = get_parent(parent); 00407 continue; 00408 } 00409 if (!sibling->right || is_black(sibling->right)) { 00410 set_color(RB_BLACK, sibling->left); 00411 set_color(RB_RED, sibling); 00412 rotate_right(sibling, tree); 00413 sibling = parent->right; 00414 } 00415 set_color(get_color(parent), sibling); 00416 set_color(RB_BLACK, parent); 00417 set_color(RB_BLACK, sibling->right); 00418 rotate_left(parent, tree); 00419 node = tree->root; 00420 break; 00421 } else { 00422 struct rbtree_node *sibling = parent->left; 00423 00424 if (is_red(sibling)) { 00425 set_color(RB_BLACK, sibling); 00426 set_color(RB_RED, parent); 00427 rotate_right(parent, tree); 00428 sibling = parent->left; 00429 } 00430 if ((!sibling->left || is_black(sibling->left)) && 00431 (!sibling->right || is_black(sibling->right))) { 00432 set_color(RB_RED, sibling); 00433 node = parent; 00434 parent = get_parent(parent); 00435 continue; 00436 } 00437 if (!sibling->left || is_black(sibling->left)) { 00438 set_color(RB_BLACK, sibling->right); 00439 set_color(RB_RED, sibling); 00440 rotate_left(sibling, tree); 00441 sibling = parent->left; 00442 } 00443 set_color(get_color(parent), sibling); 00444 set_color(RB_BLACK, parent); 00445 set_color(RB_BLACK, sibling->left); 00446 rotate_right(parent, tree); 00447 node = tree->root; 00448 break; 00449 } 00450 } while (is_black(node)); 00451 00452 if (node) 00453 set_color(RB_BLACK, node); 00454 } 00455 00456 void rbtree_replace(struct rbtree_node *old, struct rbtree_node *new, 00457 struct rbtree *tree) 00458 { 00459 struct rbtree_node *parent = get_parent(old); 00460 00461 if (parent) 00462 set_child(parent, new, parent->left == old); 00463 else 00464 tree->root = new; 00465 00466 if (old->left) 00467 set_parent(new, old->left); 00468 if (old->right) 00469 set_parent(new, old->right); 00470 00471 if (tree->first == old) 00472 tree->first = new; 00473 if (tree->last == old) 00474 tree->last = new; 00475 00476 *new = *old; 00477 } 00478 00479 int rbtree_init(struct rbtree *tree, rbtree_cmp_fn_t fn, unsigned long flags) 00480 { 00481 if (flags) 00482 return -1; 00483 tree->root = NULL; 00484 tree->cmp_fn = fn; 00485 tree->first = NULL; 00486 tree->last = NULL; 00487 return 0; 00488 }