nfs-ganesha 1.4
|
00001 /* 00002 * avltree - Implements an AVL 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 #ifdef HAVE_CONFIG_H 00022 #include "config.h" 00023 #endif 00024 #include <assert.h> 00025 00026 #include "avltree.h" 00027 00028 00029 #if !defined UINTPTR_MAX || UINTPTR_MAX != UINT64_MAX 00030 00031 static inline int is_root(struct avltree_node *node) 00032 { 00033 return node->parent == NULL; 00034 } 00035 00036 static inline void INIT_NODE(struct avltree_node *node) 00037 { 00038 node->left = NULL; 00039 node->right = NULL; 00040 node->parent = NULL; 00041 node->balance = 0; 00042 } 00043 00044 static inline signed get_balance(struct avltree_node *node) 00045 { 00046 return node->balance; 00047 } 00048 00049 static inline void set_balance(int balance, struct avltree_node *node) 00050 { 00051 node->balance = balance; 00052 } 00053 00054 static inline int inc_balance(struct avltree_node *node) 00055 { 00056 return ++node->balance; 00057 } 00058 00059 static inline int dec_balance(struct avltree_node *node) 00060 { 00061 return --node->balance; 00062 } 00063 00064 static inline struct avltree_node *get_parent(const struct avltree_node *node) 00065 { 00066 return node->parent; 00067 } 00068 00069 static inline void set_parent(struct avltree_node *parent, 00070 struct avltree_node *node) 00071 { 00072 node->parent = parent; 00073 } 00074 00075 #else 00076 00077 static inline int is_root(struct avltree_node *node) 00078 { 00079 return !(node->parent & ~7UL); 00080 } 00081 00082 static inline void INIT_NODE(struct avltree_node *node) 00083 { 00084 node->left = NULL; 00085 node->right = NULL; 00086 node->parent = 2; 00087 } 00088 00089 static inline signed get_balance(struct avltree_node *node) 00090 { 00091 return (int)(node->parent & 7) - 2; 00092 } 00093 00094 static inline void set_balance(int balance, struct avltree_node *node) 00095 { 00096 node->parent = (node->parent & ~7UL) | (balance + 2); 00097 } 00098 00099 static inline int inc_balance(struct avltree_node *node) 00100 { 00101 return (int)(++node->parent & 7) - 2; 00102 } 00103 00104 static inline int dec_balance(struct avltree_node *node) 00105 { 00106 return (int)(--node->parent & 7) - 2; 00107 } 00108 00109 static inline struct avltree_node *get_parent(const struct avltree_node *node) 00110 { 00111 return (struct avltree_node *)(node->parent & ~7UL); 00112 } 00113 00114 static inline void set_parent(const struct avltree_node *parent, 00115 struct avltree_node *node) 00116 { 00117 node->parent = (uintptr_t)parent | (node->parent & 7); 00118 } 00119 00120 #endif 00121 00122 /* 00123 * Iterators 00124 */ 00125 static inline struct avltree_node *get_first(struct avltree_node *node) 00126 { 00127 while (node->left) 00128 node = node->left; 00129 return node; 00130 } 00131 00132 static inline struct avltree_node *get_last(struct avltree_node *node) 00133 { 00134 while (node->right) 00135 node = node->right; 00136 return node; 00137 } 00138 00139 struct avltree_node *avltree_first(const struct avltree *tree) 00140 { 00141 return tree->first; 00142 } 00143 00144 struct avltree_node *avltree_last(const struct avltree *tree) 00145 { 00146 return tree->last; 00147 } 00148 00149 struct avltree_node *avltree_next(const struct avltree_node *node) 00150 { 00151 struct avltree_node *parent; 00152 00153 if (node->right) 00154 return get_first(node->right); 00155 00156 while ((parent = get_parent(node)) && parent->right == node) 00157 node = parent; 00158 return parent; 00159 } 00160 00161 struct avltree_node *avltree_prev(const struct avltree_node *node) 00162 { 00163 struct avltree_node *parent; 00164 00165 if (node->left) 00166 return get_last(node->left); 00167 00168 while ((parent = get_parent(node)) && parent->left == node) 00169 node = parent; 00170 return parent; 00171 } 00172 00173 uint64_t avltree_size(const struct avltree *tree) 00174 { 00175 return tree->size; 00176 } 00177 00178 /* 00179 * The AVL tree is more rigidly balanced than Red-Black trees, leading 00180 * to slower insertion and removal but faster retrieval. 00181 */ 00182 00183 /* node->balance = height(node->right) - height(node->left); */ 00184 static void rotate_left(struct avltree_node *node, struct avltree *tree) 00185 { 00186 struct avltree_node *p = node; 00187 struct avltree_node *q = node->right; /* can't be NULL */ 00188 struct avltree_node *parent = get_parent(p); 00189 00190 if (!is_root(p)) { 00191 if (parent->left == p) 00192 parent->left = q; 00193 else 00194 parent->right = q; 00195 } else 00196 tree->root = q; 00197 set_parent(parent, q); 00198 set_parent(q, p); 00199 00200 p->right = q->left; 00201 if (p->right) 00202 set_parent(p, p->right); 00203 q->left = p; 00204 } 00205 00206 static void rotate_right(struct avltree_node *node, struct avltree *tree) 00207 { 00208 struct avltree_node *p = node; 00209 struct avltree_node *q = node->left; /* can't be NULL */ 00210 struct avltree_node *parent = get_parent(p); 00211 00212 if (!is_root(p)) { 00213 if (parent->left == p) 00214 parent->left = q; 00215 else 00216 parent->right = q; 00217 } else 00218 tree->root = q; 00219 set_parent(parent, q); 00220 set_parent(q, p); 00221 00222 p->left = q->right; 00223 if (p->left) 00224 set_parent(p, p->left); 00225 q->right = p; 00226 } 00227 00228 /* 00229 * 'pparent', 'unbalanced' and 'is_left' are only used for 00230 * insertions. Normally GCC will notice this and get rid of them for 00231 * lookups. 00232 */ 00233 static inline struct avltree_node *do_lookup(const struct avltree_node *key, 00234 const struct avltree *tree, 00235 struct avltree_node **pparent, 00236 struct avltree_node **unbalanced, 00237 int *is_left) 00238 { 00239 struct avltree_node *node = tree->root; 00240 int res = 0; 00241 00242 *pparent = NULL; 00243 *unbalanced = node; 00244 *is_left = 0; 00245 00246 while (node) { 00247 if (get_balance(node) != 0) 00248 *unbalanced = node; 00249 00250 res = tree->cmp_fn(node, key); 00251 if (res == 0) 00252 return node; 00253 *pparent = node; 00254 if ((*is_left = res > 0)) 00255 node = node->left; 00256 else 00257 node = node->right; 00258 } 00259 return NULL; 00260 } 00261 00262 struct avltree_node *avltree_lookup(const struct avltree_node *key, 00263 const struct avltree *tree) 00264 { 00265 struct avltree_node *parent, *unbalanced; 00266 int is_left; 00267 00268 return do_lookup(key, tree, &parent, &unbalanced, &is_left); 00269 } 00270 00271 struct avltree_node *avltree_inf(const struct avltree_node *key, 00272 const struct avltree *tree) 00273 { 00274 struct avltree_node *parent __attribute__((unused)); 00275 struct avltree_node *lb; 00276 struct avltree_node *unbalanced __attribute__((unused)); 00277 struct avltree_node *node = tree->root; 00278 int is_left = 0; 00279 int res = 0; 00280 00281 lb = avltree_first(tree); /* at worst, the first entry */ 00282 unbalanced = node; 00283 parent = NULL; 00284 is_left = 0; 00285 00286 while (node) { 00287 if (get_balance(node) != 0) 00288 unbalanced = node; 00289 res = tree->cmp_fn(node, key); 00290 if (res == 0) { 00291 /* node is the infimum */ 00292 return node; 00293 } 00294 else if (res < 1) /* lb is less than key */ 00295 lb = node; 00296 parent = node; 00297 if ((is_left = res > 0)) 00298 node = node->left; 00299 else 00300 node = node->right; 00301 } /* while */ 00302 00303 return (lb); 00304 } 00305 00306 struct avltree_node *avltree_sup(const struct avltree_node *key, 00307 const struct avltree *tree) 00308 { 00309 struct avltree_node *parent __attribute__((unused)); 00310 struct avltree_node *ub = NULL; 00311 struct avltree_node *unbalanced __attribute__((unused)); 00312 struct avltree_node *node = tree->root; 00313 int is_left = 0; 00314 int res = 0; 00315 00316 unbalanced = node; 00317 parent = NULL; 00318 is_left = 0; 00319 ub = node; 00320 while (node) { 00321 if (get_balance(node) != 0) 00322 unbalanced = node; 00323 res = tree->cmp_fn(node, key); 00324 if (res == 0) { 00325 /* node is the supremum */ 00326 return (node); 00327 } 00328 parent = node; 00329 if ((is_left = res > 0)) 00330 node = node->left; 00331 else 00332 node = node->right; 00333 if (node) { 00334 res = tree->cmp_fn(node, key); 00335 if(res > 0) /* XXX do we need reciprocal test on ub? */ 00336 ub = node; 00337 } 00338 } /* while */ 00339 00340 return (ub); 00341 } 00342 00343 static void set_child(struct avltree_node *child, 00344 struct avltree_node *node, int left) 00345 { 00346 if (left) 00347 node->left = child; 00348 else 00349 node->right = child; 00350 } 00351 00352 /* Insertion never needs more than 2 rotations */ 00353 struct avltree_node *avltree_insert(struct avltree_node *node, struct avltree *tree) 00354 { 00355 struct avltree_node *key, *parent, *unbalanced; 00356 int is_left; 00357 00358 key = do_lookup(node, tree, &parent, &unbalanced, &is_left); 00359 if (key) 00360 return key; 00361 00362 INIT_NODE(node); 00363 00364 if (!parent) { 00365 tree->root = node; 00366 tree->first = tree->last = node; 00367 tree->height++; 00368 tree->size++; 00369 return NULL; 00370 } 00371 if (is_left) { 00372 if (parent == tree->first) 00373 tree->first = node; 00374 } else { 00375 if (parent == tree->last) 00376 tree->last = node; 00377 } 00378 set_parent(parent, node); 00379 set_child(node, parent, is_left); 00380 00381 for (;;) { 00382 if (parent->left == node) 00383 dec_balance(parent); 00384 else 00385 inc_balance(parent); 00386 00387 if (parent == unbalanced) 00388 break; 00389 node = parent; 00390 parent = get_parent(parent); 00391 } 00392 00393 /* inserted */ 00394 tree->size++; 00395 00396 switch (get_balance(unbalanced)) { 00397 case 1: case -1: 00398 tree->height++; 00399 /* fall through */ 00400 case 0: 00401 break; 00402 case 2: { 00403 struct avltree_node *right = unbalanced->right; 00404 00405 if (get_balance(right) == 1) { 00406 set_balance(0, unbalanced); 00407 set_balance(0, right); 00408 } else { 00409 switch (get_balance(right->left)) { 00410 case 1: 00411 set_balance(-1, unbalanced); 00412 set_balance( 0, right); 00413 break; 00414 case 0: 00415 set_balance(0, unbalanced); 00416 set_balance(0, right); 00417 break; 00418 case -1: 00419 set_balance(0, unbalanced); 00420 set_balance(1, right); 00421 break; 00422 } 00423 set_balance(0, right->left); 00424 00425 rotate_right(right, tree); 00426 } 00427 rotate_left(unbalanced, tree); 00428 break; 00429 } 00430 case -2: { 00431 struct avltree_node *left = unbalanced->left; 00432 00433 if (get_balance(left) == -1) { 00434 set_balance(0, unbalanced); 00435 set_balance(0, left); 00436 } else { 00437 switch (get_balance(left->right)) { 00438 case 1: 00439 set_balance( 0, unbalanced); 00440 set_balance(-1, left); 00441 break; 00442 case 0: 00443 set_balance(0, unbalanced); 00444 set_balance(0, left); 00445 break; 00446 case -1: 00447 set_balance(1, unbalanced); 00448 set_balance(0, left); 00449 break; 00450 } 00451 set_balance(0, left->right); 00452 00453 rotate_left(left, tree); 00454 } 00455 rotate_right(unbalanced, tree); 00456 break; 00457 } 00458 } 00459 return NULL; 00460 } 00461 00462 /* Deletion might require up to log(n) rotations */ 00463 void avltree_remove(struct avltree_node *node, struct avltree *tree) 00464 { 00465 struct avltree_node *parent = get_parent(node); 00466 struct avltree_node *left = node->left; 00467 struct avltree_node *right = node->right; 00468 struct avltree_node *next; 00469 int is_left = is_left; 00470 00471 if (node == tree->first) 00472 tree->first = avltree_next(node); 00473 if (node == tree->last) 00474 tree->last = avltree_prev(node); 00475 00476 if (!left) 00477 next = right; 00478 else if (!right) 00479 next = left; 00480 else 00481 next = get_first(right); 00482 00483 if (parent) { 00484 is_left = parent->left == node; 00485 set_child(next, parent, is_left); 00486 } else 00487 tree->root = next; 00488 00489 if (left && right) { 00490 set_balance(get_balance(node), next); 00491 00492 next->left = left; 00493 set_parent(next, left); 00494 00495 if (next != right) { 00496 parent = get_parent(next); 00497 set_parent(get_parent(node), next); 00498 00499 node = next->right; 00500 parent->left = node; 00501 is_left = 1; 00502 00503 next->right = right; 00504 set_parent(next, right); 00505 } else { 00506 set_parent(parent, next); 00507 parent = next; 00508 node = parent->right; 00509 is_left = 0; 00510 } 00511 assert(parent != NULL); 00512 } else 00513 node = next; 00514 00515 if (node) 00516 set_parent(parent, node); 00517 00518 /* removed */ 00519 tree->size--; 00520 00521 /* 00522 * At this point, 'parent' can only be null, if 'node' is the 00523 * tree's root and has at most one child. 00524 * 00525 * case 1: the subtree is now balanced but its height has 00526 * decreased. 00527 * 00528 * case 2: the subtree is mostly balanced and its height is 00529 * unchanged. 00530 * 00531 * case 3: the subtree is unbalanced and its height may have 00532 * been changed during the rebalancing process, see below. 00533 * 00534 * case 3.1: after a left rotation, the subtree becomes mostly 00535 * balanced and its height is unchanged. 00536 * 00537 * case 3.2: after a left rotation, the subtree becomes 00538 * balanced but its height has decreased. 00539 * 00540 * case 3.3: after a left and a right rotation, the subtree 00541 * becomes balanced or mostly balanced but its height has 00542 * decreased for all cases. 00543 */ 00544 while (parent) { 00545 int balance; 00546 node = parent; 00547 parent = get_parent(parent); 00548 00549 if (is_left) { 00550 is_left = parent && parent->left == node; 00551 00552 balance = inc_balance(node); 00553 if (balance == 0) /* case 1 */ 00554 continue; 00555 if (balance == 1) /* case 2 */ 00556 return; 00557 right = node->right; /* case 3 */ 00558 switch (get_balance(right)) { 00559 case 0: /* case 3.1 */ 00560 set_balance( 1, node); 00561 set_balance(-1, right); 00562 rotate_left(node, tree); 00563 return; 00564 case 1: /* case 3.2 */ 00565 set_balance(0, node); 00566 set_balance(0, right); 00567 break; 00568 case -1: /* case 3.3 */ 00569 switch (get_balance(right->left)) { 00570 case 1: 00571 set_balance(-1, node); 00572 set_balance( 0, right); 00573 break; 00574 case 0: 00575 set_balance(0, node); 00576 set_balance(0, right); 00577 break; 00578 case -1: 00579 set_balance(0, node); 00580 set_balance(1, right); 00581 break; 00582 } 00583 set_balance(0, right->left); 00584 00585 rotate_right(right, tree); 00586 } 00587 rotate_left(node, tree); 00588 } else { 00589 is_left = parent && parent->left == node; 00590 00591 balance = dec_balance(node); 00592 if (balance == 0) 00593 continue; 00594 if (balance == -1) 00595 return; 00596 left = node->left; 00597 switch (get_balance(left)) { 00598 case 0: 00599 set_balance(-1, node); 00600 set_balance(1, left); 00601 rotate_right(node, tree); 00602 return; 00603 case -1: 00604 set_balance(0, node); 00605 set_balance(0, left); 00606 break; 00607 case 1: 00608 switch (get_balance(left->right)) { 00609 case 1: 00610 set_balance(0, node); 00611 set_balance(-1, left); 00612 break; 00613 case 0: 00614 set_balance(0, node); 00615 set_balance(0, left); 00616 break; 00617 case -1: 00618 set_balance(1, node); 00619 set_balance(0, left); 00620 break; 00621 } 00622 set_balance(0, left->right); 00623 00624 rotate_left(left, tree); 00625 } 00626 rotate_right(node, tree); 00627 } 00628 } 00629 tree->height--; 00630 } 00631 00632 void avltree_replace(struct avltree_node *old, struct avltree_node *new, 00633 struct avltree *tree) 00634 { 00635 struct avltree_node *parent = get_parent(old); 00636 00637 if (parent) 00638 set_child(parent, new, parent->left == old); 00639 else { 00640 /* I'm skeptical this case should be permitted--this 00641 * says that if old is not in the tree, just make new 00642 * the root of the tree */ 00643 tree->root = new; 00644 tree->size++; 00645 } 00646 00647 if (old->left) 00648 set_parent(new, old->left); 00649 if (old->right) 00650 set_parent(new, old->right); 00651 00652 if (tree->first == old) 00653 tree->first = new; 00654 if (tree->last == old) 00655 tree->last = new; 00656 00657 *new = *old; 00658 } 00659 00660 int avltree_init(struct avltree *tree, avltree_cmp_fn_t cmp, unsigned long flags) 00661 { 00662 if (flags) 00663 return -1; 00664 tree->root = NULL; 00665 tree->cmp_fn = cmp; 00666 tree->height = -1; 00667 tree->first = NULL; 00668 tree->last = NULL; 00669 tree->size = 0; 00670 return 0; 00671 }