1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 30 /* 31 * AVL - generic AVL tree implementation for kernel use 32 * 33 * A complete description of AVL trees can be found in many CS textbooks. 34 * 35 * Here is a very brief overview. An AVL tree is a binary search tree that is 36 * almost perfectly balanced. By "almost" perfectly balanced, we mean that at 37 * any given node, the left and right subtrees are allowed to differ in height 38 * by at most 1 level. 39 * 40 * This relaxation from a perfectly balanced binary tree allows doing 41 * insertion and deletion relatively efficiently. Searching the tree is 42 * still a fast operation, roughly O(log(N)). 43 * 44 * The key to insertion and deletion is a set of tree maniuplations called 45 * rotations, which bring unbalanced subtrees back into the semi-balanced state. 46 * 47 * This implementation of AVL trees has the following peculiarities: 48 * 49 * - The AVL specific data structures are physically embedded as fields 50 * in the "using" data structures. To maintain generality the code 51 * must constantly translate between "avl_node_t *" and containing 52 * data structure "void *"s by adding/subracting the avl_offset. 53 * 54 * - Since the AVL data is always embedded in other structures, there is 55 * no locking or memory allocation in the AVL routines. This must be 56 * provided for by the enclosing data structure's semantics. Typically, 57 * avl_insert()/_add()/_remove()/avl_insert_here() require some kind of 58 * exclusive write lock. Other operations require a read lock. 59 * 60 * - The implementation uses iteration instead of explicit recursion, 61 * since it is intended to run on limited size kernel stacks. Since 62 * there is no recursion stack present to move "up" in the tree, 63 * there is an explicit "parent" link in the avl_node_t. 64 * 65 * - The left/right children pointers of a node are in an array. 66 * In the code, variables (instead of constants) are used to represent 67 * left and right indices. The implementation is written as if it only 68 * dealt with left handed manipulations. By changing the value assigned 69 * to "left", the code also works for right handed trees. The 70 * following variables/terms are frequently used: 71 * 72 * int left; // 0 when dealing with left children, 73 * // 1 for dealing with right children 74 * 75 * int left_heavy; // -1 when left subtree is taller at some node, 76 * // +1 when right subtree is taller 77 * 78 * int right; // will be the opposite of left (0 or 1) 79 * int right_heavy;// will be the opposite of left_heavy (-1 or 1) 80 * 81 * int direction; // 0 for "<" (ie. left child); 1 for ">" (right) 82 * 83 * Though it is a little more confusing to read the code, the approach 84 * allows using half as much code (and hence cache footprint) for tree 85 * manipulations and eliminates many conditional branches. 86 * 87 * - The avl_index_t is an opaque "cookie" used to find nodes at or 88 * adjacent to where a new value would be inserted in the tree. The value 89 * is a modified "avl_node_t *". The bottom bit (normally 0 for a 90 * pointer) is set to indicate if that the new node has a value greater 91 * than the value of the indicated "avl_node_t *". 92 */ 93 94 #include <sys/types.h> 95 #include <sys/param.h> 96 #include <sys/debug.h> 97 #include <sys/avl.h> 98 #include <sys/cmn_err.h> 99 100 /* 101 * Small arrays to translate between balance (or diff) values and child indeces. 102 * 103 * Code that deals with binary tree data structures will randomly use 104 * left and right children when examining a tree. C "if()" statements 105 * which evaluate randomly suffer from very poor hardware branch prediction. 106 * In this code we avoid some of the branch mispredictions by using the 107 * following translation arrays. They replace random branches with an 108 * additional memory reference. Since the translation arrays are both very 109 * small the data should remain efficiently in cache. 110 */ 111 static const int avl_child2balance[2] = {-1, 1}; 112 static const int avl_balance2child[] = {0, 0, 1}; 113 114 115 /* 116 * Walk from one node to the previous valued node (ie. an infix walk 117 * towards the left). At any given node we do one of 2 things: 118 * 119 * - If there is a left child, go to it, then to it's rightmost descendant. 120 * 121 * - otherwise we return thru parent nodes until we've come from a right child. 122 * 123 * Return Value: 124 * NULL - if at the end of the nodes 125 * otherwise next node 126 */ 127 void * 128 avl_walk(avl_tree_t *tree, void *oldnode, int left) 129 { 130 size_t off = tree->avl_offset; 131 avl_node_t *node = AVL_DATA2NODE(oldnode, off); 132 int right = 1 - left; 133 int was_child; 134 135 136 /* 137 * nowhere to walk to if tree is empty 138 */ 139 if (node == NULL) 140 return (NULL); 141 142 /* 143 * Visit the previous valued node. There are two possibilities: 144 * 145 * If this node has a left child, go down one left, then all 146 * the way right. 147 */ 148 if (node->avl_child[left] != NULL) { 149 for (node = node->avl_child[left]; 150 node->avl_child[right] != NULL; 151 node = node->avl_child[right]) 152 ; 153 /* 154 * Otherwise, return thru left children as far as we can. 155 */ 156 } else { 157 for (;;) { 158 was_child = AVL_XCHILD(node); 159 node = AVL_XPARENT(node); 160 if (node == NULL) 161 return (NULL); 162 if (was_child == right) 163 break; 164 } 165 } 166 167 return (AVL_NODE2DATA(node, off)); 168 } 169 170 /* 171 * Return the lowest valued node in a tree or NULL. 172 * (leftmost child from root of tree) 173 */ 174 void * 175 avl_first(avl_tree_t *tree) 176 { 177 avl_node_t *node; 178 avl_node_t *prev = NULL; 179 size_t off = tree->avl_offset; 180 181 for (node = tree->avl_root; node != NULL; node = node->avl_child[0]) 182 prev = node; 183 184 if (prev != NULL) 185 return (AVL_NODE2DATA(prev, off)); 186 return (NULL); 187 } 188 189 /* 190 * Return the highest valued node in a tree or NULL. 191 * (rightmost child from root of tree) 192 */ 193 void * 194 avl_last(avl_tree_t *tree) 195 { 196 avl_node_t *node; 197 avl_node_t *prev = NULL; 198 size_t off = tree->avl_offset; 199 200 for (node = tree->avl_root; node != NULL; node = node->avl_child[1]) 201 prev = node; 202 203 if (prev != NULL) 204 return (AVL_NODE2DATA(prev, off)); 205 return (NULL); 206 } 207 208 /* 209 * Access the node immediately before or after an insertion point. 210 * 211 * "avl_index_t" is a (avl_node_t *) with the bottom bit indicating a child 212 * 213 * Return value: 214 * NULL: no node in the given direction 215 * "void *" of the found tree node 216 */ 217 void * 218 avl_nearest(avl_tree_t *tree, avl_index_t where, int direction) 219 { 220 int child = AVL_INDEX2CHILD(where); 221 avl_node_t *node = AVL_INDEX2NODE(where); 222 void *data; 223 size_t off = tree->avl_offset; 224 225 if (node == NULL) { 226 ASSERT(tree->avl_root == NULL); 227 return (NULL); 228 } 229 data = AVL_NODE2DATA(node, off); 230 if (child != direction) 231 return (data); 232 233 return (avl_walk(tree, data, direction)); 234 } 235 236 237 /* 238 * Search for the node which contains "value". The algorithm is a 239 * simple binary tree search. 240 * 241 * return value: 242 * NULL: the value is not in the AVL tree 243 * *where (if not NULL) is set to indicate the insertion point 244 * "void *" of the found tree node 245 */ 246 void * 247 avl_find(avl_tree_t *tree, void *value, avl_index_t *where) 248 { 249 avl_node_t *node; 250 avl_node_t *prev = NULL; 251 int child = 0; 252 int diff; 253 size_t off = tree->avl_offset; 254 255 for (node = tree->avl_root; node != NULL; 256 node = node->avl_child[child]) { 257 258 prev = node; 259 260 diff = tree->avl_compar(value, AVL_NODE2DATA(node, off)); 261 ASSERT(-1 <= diff && diff <= 1); 262 if (diff == 0) { 263 #ifdef DEBUG 264 if (where != NULL) 265 *where = NULL; 266 #endif 267 return (AVL_NODE2DATA(node, off)); 268 } 269 child = avl_balance2child[1 + diff]; 270 271 } 272 273 if (where != NULL) 274 *where = AVL_MKINDEX(prev, child); 275 276 return (NULL); 277 } 278 279 280 /* 281 * Perform a rotation to restore balance at the subtree given by depth. 282 * 283 * This routine is used by both insertion and deletion. The return value 284 * indicates: 285 * 0 : subtree did not change height 286 * !0 : subtree was reduced in height 287 * 288 * The code is written as if handling left rotations, right rotations are 289 * symmetric and handled by swapping values of variables right/left[_heavy] 290 * 291 * On input balance is the "new" balance at "node". This value is either 292 * -2 or +2. 293 */ 294 static int 295 avl_rotation(avl_tree_t *tree, avl_node_t *node, int balance) 296 { 297 int left = !(balance < 0); /* when balance = -2, left will be 0 */ 298 int right = 1 - left; 299 int left_heavy = balance >> 1; 300 int right_heavy = -left_heavy; 301 avl_node_t *parent = AVL_XPARENT(node); 302 avl_node_t *child = node->avl_child[left]; 303 avl_node_t *cright; 304 avl_node_t *gchild; 305 avl_node_t *gright; 306 avl_node_t *gleft; 307 int which_child = AVL_XCHILD(node); 308 int child_bal = AVL_XBALANCE(child); 309 310 /* BEGIN CSTYLED */ 311 /* 312 * case 1 : node is overly left heavy, the left child is balanced or 313 * also left heavy. This requires the following rotation. 314 * 315 * (node bal:-2) 316 * / \ 317 * / \ 318 * (child bal:0 or -1) 319 * / \ 320 * / \ 321 * cright 322 * 323 * becomes: 324 * 325 * (child bal:1 or 0) 326 * / \ 327 * / \ 328 * (node bal:-1 or 0) 329 * / \ 330 * / \ 331 * cright 332 * 333 * we detect this situation by noting that child's balance is not 334 * right_heavy. 335 */ 336 /* END CSTYLED */ 337 if (child_bal != right_heavy) { 338 339 /* 340 * compute new balance of nodes 341 * 342 * If child used to be left heavy (now balanced) we reduced 343 * the height of this sub-tree -- used in "return...;" below 344 */ 345 child_bal += right_heavy; /* adjust towards right */ 346 347 /* 348 * move "cright" to be node's left child 349 */ 350 cright = child->avl_child[right]; 351 node->avl_child[left] = cright; 352 if (cright != NULL) { 353 AVL_SETPARENT(cright, node); 354 AVL_SETCHILD(cright, left); 355 } 356 357 /* 358 * move node to be child's right child 359 */ 360 child->avl_child[right] = node; 361 AVL_SETBALANCE(node, -child_bal); 362 AVL_SETCHILD(node, right); 363 AVL_SETPARENT(node, child); 364 365 /* 366 * update the pointer into this subtree 367 */ 368 AVL_SETBALANCE(child, child_bal); 369 AVL_SETCHILD(child, which_child); 370 AVL_SETPARENT(child, parent); 371 if (parent != NULL) 372 parent->avl_child[which_child] = child; 373 else 374 tree->avl_root = child; 375 376 return (child_bal == 0); 377 } 378 379 /* BEGIN CSTYLED */ 380 /* 381 * case 2 : When node is left heavy, but child is right heavy we use 382 * a different rotation. 383 * 384 * (node b:-2) 385 * / \ 386 * / \ 387 * / \ 388 * (child b:+1) 389 * / \ 390 * / \ 391 * (gchild b: != 0) 392 * / \ 393 * / \ 394 * gleft gright 395 * 396 * becomes: 397 * 398 * (gchild b:0) 399 * / \ 400 * / \ 401 * / \ 402 * (child b:?) (node b:?) 403 * / \ / \ 404 * / \ / \ 405 * gleft gright 406 * 407 * computing the new balances is more complicated. As an example: 408 * if gchild was right_heavy, then child is now left heavy 409 * else it is balanced 410 */ 411 /* END CSTYLED */ 412 gchild = child->avl_child[right]; 413 gleft = gchild->avl_child[left]; 414 gright = gchild->avl_child[right]; 415 416 /* 417 * move gright to left child of node and 418 * 419 * move gleft to right child of node 420 */ 421 node->avl_child[left] = gright; 422 if (gright != NULL) { 423 AVL_SETPARENT(gright, node); 424 AVL_SETCHILD(gright, left); 425 } 426 427 child->avl_child[right] = gleft; 428 if (gleft != NULL) { 429 AVL_SETPARENT(gleft, child); 430 AVL_SETCHILD(gleft, right); 431 } 432 433 /* 434 * move child to left child of gchild and 435 * 436 * move node to right child of gchild and 437 * 438 * fixup parent of all this to point to gchild 439 */ 440 balance = AVL_XBALANCE(gchild); 441 gchild->avl_child[left] = child; 442 AVL_SETBALANCE(child, (balance == right_heavy ? left_heavy : 0)); 443 AVL_SETPARENT(child, gchild); 444 AVL_SETCHILD(child, left); 445 446 gchild->avl_child[right] = node; 447 AVL_SETBALANCE(node, (balance == left_heavy ? right_heavy : 0)); 448 AVL_SETPARENT(node, gchild); 449 AVL_SETCHILD(node, right); 450 451 AVL_SETBALANCE(gchild, 0); 452 AVL_SETPARENT(gchild, parent); 453 AVL_SETCHILD(gchild, which_child); 454 if (parent != NULL) 455 parent->avl_child[which_child] = gchild; 456 else 457 tree->avl_root = gchild; 458 459 return (1); /* the new tree is always shorter */ 460 } 461 462 463 /* 464 * Insert a new node into an AVL tree at the specified (from avl_find()) place. 465 * 466 * Newly inserted nodes are always leaf nodes in the tree, since avl_find() 467 * searches out to the leaf positions. The avl_index_t indicates the node 468 * which will be the parent of the new node. 469 * 470 * After the node is inserted, a single rotation further up the tree may 471 * be necessary to maintain an acceptable AVL balance. 472 */ 473 void 474 avl_insert(avl_tree_t *tree, void *new_data, avl_index_t where) 475 { 476 avl_node_t *node; 477 avl_node_t *parent = AVL_INDEX2NODE(where); 478 int old_balance; 479 int new_balance; 480 int which_child = AVL_INDEX2CHILD(where); 481 size_t off = tree->avl_offset; 482 483 ASSERT(tree); 484 #ifdef _LP64 485 ASSERT(((uintptr_t)new_data & 0x7) == 0); 486 #endif 487 488 node = AVL_DATA2NODE(new_data, off); 489 490 /* 491 * First, add the node to the tree at the indicated position. 492 */ 493 ++tree->avl_numnodes; 494 495 node->avl_child[0] = NULL; 496 node->avl_child[1] = NULL; 497 498 AVL_SETCHILD(node, which_child); 499 AVL_SETBALANCE(node, 0); 500 AVL_SETPARENT(node, parent); 501 if (parent != NULL) { 502 ASSERT(parent->avl_child[which_child] == NULL); 503 parent->avl_child[which_child] = node; 504 } else { 505 ASSERT(tree->avl_root == NULL); 506 tree->avl_root = node; 507 } 508 /* 509 * Now, back up the tree modifying the balance of all nodes above the 510 * insertion point. If we get to a highly unbalanced ancestor, we 511 * need to do a rotation. If we back out of the tree we are done. 512 * If we brought any subtree into perfect balance (0), we are also done. 513 */ 514 for (;;) { 515 node = parent; 516 if (node == NULL) 517 return; 518 519 /* 520 * Compute the new balance 521 */ 522 old_balance = AVL_XBALANCE(node); 523 new_balance = old_balance + avl_child2balance[which_child]; 524 525 /* 526 * If we introduced equal balance, then we are done immediately 527 */ 528 if (new_balance == 0) { 529 AVL_SETBALANCE(node, 0); 530 return; 531 } 532 533 /* 534 * If both old and new are not zero we went 535 * from -1 to -2 balance, do a rotation. 536 */ 537 if (old_balance != 0) 538 break; 539 540 AVL_SETBALANCE(node, new_balance); 541 parent = AVL_XPARENT(node); 542 which_child = AVL_XCHILD(node); 543 } 544 545 /* 546 * perform a rotation to fix the tree and return 547 */ 548 (void) avl_rotation(tree, node, new_balance); 549 } 550 551 /* 552 * Insert "new_data" in "tree" in the given "direction" either after or 553 * before (AVL_AFTER, AVL_BEFORE) the data "here". 554 * 555 * Insertions can only be done at empty leaf points in the tree, therefore 556 * if the given child of the node is already present we move to either 557 * the AVL_PREV or AVL_NEXT and reverse the insertion direction. Since 558 * every other node in the tree is a leaf, this always works. 559 * 560 * To help developers using this interface, we assert that the new node 561 * is correctly ordered at every step of the way in DEBUG kernels. 562 */ 563 void 564 avl_insert_here( 565 avl_tree_t *tree, 566 void *new_data, 567 void *here, 568 int direction) 569 { 570 avl_node_t *node; 571 int child = direction; /* rely on AVL_BEFORE == 0, AVL_AFTER == 1 */ 572 573 ASSERT(tree != NULL); 574 ASSERT(new_data != NULL); 575 ASSERT(here != NULL); 576 ASSERT(direction == AVL_BEFORE || direction == AVL_AFTER); 577 578 /* 579 * If corresponding child of node is not NULL, go to the neighboring 580 * node and reverse the insertion direction. 581 */ 582 node = AVL_DATA2NODE(here, tree->avl_offset); 583 ASSERT(tree->avl_compar(new_data, here) > 0 ? child == 1 : child == 0); 584 585 if (node->avl_child[child] != NULL) { 586 node = node->avl_child[child]; 587 child = 1 - child; 588 while (node->avl_child[child] != NULL) { 589 ASSERT(tree->avl_compar(new_data, 590 AVL_NODE2DATA(node, tree->avl_offset)) > 0 ? 591 child == 1 : child == 0); 592 node = node->avl_child[child]; 593 } 594 ASSERT(tree->avl_compar(new_data, 595 AVL_NODE2DATA(node, tree->avl_offset)) > 0 ? 596 child == 1 : child == 0); 597 } 598 ASSERT(node->avl_child[child] == NULL); 599 600 avl_insert(tree, new_data, AVL_MKINDEX(node, child)); 601 } 602 603 /* 604 * Add a new node to an AVL tree. 605 */ 606 void 607 avl_add(avl_tree_t *tree, void *new_node) 608 { 609 avl_index_t where; 610 611 /* 612 * This is unfortunate. We want to call panic() here, even for 613 * non-DEBUG kernels. In userland, however, we can't depend on anything 614 * in libc or else the rtld build process gets confused. So, all we can 615 * do in userland is resort to a normal ASSERT(). 616 */ 617 if (avl_find(tree, new_node, &where) != NULL) 618 #ifdef _KERNEL 619 panic("avl_find() succeeded inside avl_add()"); 620 #else 621 ASSERT(0); 622 #endif 623 avl_insert(tree, new_node, where); 624 } 625 626 /* 627 * Delete a node from the AVL tree. Deletion is similar to insertion, but 628 * with 2 complications. 629 * 630 * First, we may be deleting an interior node. Consider the following subtree: 631 * 632 * d c c 633 * / \ / \ / \ 634 * b e b e b e 635 * / \ / \ / 636 * a c a a 637 * 638 * When we are deleting node (d), we find and bring up an adjacent valued leaf 639 * node, say (c), to take the interior node's place. In the code this is 640 * handled by temporarily swapping (d) and (c) in the tree and then using 641 * common code to delete (d) from the leaf position. 642 * 643 * Secondly, an interior deletion from a deep tree may require more than one 644 * rotation to fix the balance. This is handled by moving up the tree through 645 * parents and applying rotations as needed. The return value from 646 * avl_rotation() is used to detect when a subtree did not change overall 647 * height due to a rotation. 648 */ 649 void 650 avl_remove(avl_tree_t *tree, void *data) 651 { 652 avl_node_t *delete; 653 avl_node_t *parent; 654 avl_node_t *node; 655 avl_node_t tmp; 656 int old_balance; 657 int new_balance; 658 int left; 659 int right; 660 int which_child; 661 size_t off = tree->avl_offset; 662 663 ASSERT(tree); 664 665 delete = AVL_DATA2NODE(data, off); 666 667 /* 668 * Deletion is easiest with a node that has at most 1 child. 669 * We swap a node with 2 children with a sequentially valued 670 * neighbor node. That node will have at most 1 child. Note this 671 * has no effect on the ordering of the remaining nodes. 672 * 673 * As an optimization, we choose the greater neighbor if the tree 674 * is right heavy, otherwise the left neighbor. This reduces the 675 * number of rotations needed. 676 */ 677 if (delete->avl_child[0] != NULL && delete->avl_child[1] != NULL) { 678 679 /* 680 * choose node to swap from whichever side is taller 681 */ 682 old_balance = AVL_XBALANCE(delete); 683 left = avl_balance2child[old_balance + 1]; 684 right = 1 - left; 685 686 /* 687 * get to the previous value'd node 688 * (down 1 left, as far as possible right) 689 */ 690 for (node = delete->avl_child[left]; 691 node->avl_child[right] != NULL; 692 node = node->avl_child[right]) 693 ; 694 695 /* 696 * create a temp placeholder for 'node' 697 * move 'node' to delete's spot in the tree 698 */ 699 tmp = *node; 700 701 *node = *delete; 702 if (node->avl_child[left] == node) 703 node->avl_child[left] = &tmp; 704 705 parent = AVL_XPARENT(node); 706 if (parent != NULL) 707 parent->avl_child[AVL_XCHILD(node)] = node; 708 else 709 tree->avl_root = node; 710 AVL_SETPARENT(node->avl_child[left], node); 711 AVL_SETPARENT(node->avl_child[right], node); 712 713 /* 714 * Put tmp where node used to be (just temporary). 715 * It always has a parent and at most 1 child. 716 */ 717 delete = &tmp; 718 parent = AVL_XPARENT(delete); 719 parent->avl_child[AVL_XCHILD(delete)] = delete; 720 which_child = (delete->avl_child[1] != 0); 721 if (delete->avl_child[which_child] != NULL) 722 AVL_SETPARENT(delete->avl_child[which_child], delete); 723 } 724 725 726 /* 727 * Here we know "delete" is at least partially a leaf node. It can 728 * be easily removed from the tree. 729 */ 730 --tree->avl_numnodes; 731 parent = AVL_XPARENT(delete); 732 which_child = AVL_XCHILD(delete); 733 if (delete->avl_child[0] != NULL) 734 node = delete->avl_child[0]; 735 else 736 node = delete->avl_child[1]; 737 738 /* 739 * Connect parent directly to node (leaving out delete). 740 */ 741 if (node != NULL) { 742 AVL_SETPARENT(node, parent); 743 AVL_SETCHILD(node, which_child); 744 } 745 if (parent == NULL) { 746 tree->avl_root = node; 747 return; 748 } 749 parent->avl_child[which_child] = node; 750 751 752 /* 753 * Since the subtree is now shorter, begin adjusting parent balances 754 * and performing any needed rotations. 755 */ 756 do { 757 758 /* 759 * Move up the tree and adjust the balance 760 * 761 * Capture the parent and which_child values for the next 762 * iteration before any rotations occur. 763 */ 764 node = parent; 765 old_balance = AVL_XBALANCE(node); 766 new_balance = old_balance - avl_child2balance[which_child]; 767 parent = AVL_XPARENT(node); 768 which_child = AVL_XCHILD(node); 769 770 /* 771 * If a node was in perfect balance but isn't anymore then 772 * we can stop, since the height didn't change above this point 773 * due to a deletion. 774 */ 775 if (old_balance == 0) { 776 AVL_SETBALANCE(node, new_balance); 777 break; 778 } 779 780 /* 781 * If the new balance is zero, we don't need to rotate 782 * else 783 * need a rotation to fix the balance. 784 * If the rotation doesn't change the height 785 * of the sub-tree we have finished adjusting. 786 */ 787 if (new_balance == 0) 788 AVL_SETBALANCE(node, new_balance); 789 else if (!avl_rotation(tree, node, new_balance)) 790 break; 791 } while (parent != NULL); 792 } 793 794 /* 795 * initialize a new AVL tree 796 */ 797 void 798 avl_create(avl_tree_t *tree, int (*compar) (const void *, const void *), 799 size_t size, size_t offset) 800 { 801 ASSERT(tree); 802 ASSERT(compar); 803 ASSERT(size > 0); 804 ASSERT(size >= offset + sizeof (avl_node_t)); 805 #ifdef _LP64 806 ASSERT((offset & 0x7) == 0); 807 #endif 808 809 tree->avl_compar = compar; 810 tree->avl_root = NULL; 811 tree->avl_numnodes = 0; 812 tree->avl_size = size; 813 tree->avl_offset = offset; 814 } 815 816 /* 817 * Delete a tree. 818 */ 819 /* ARGSUSED */ 820 void 821 avl_destroy(avl_tree_t *tree) 822 { 823 ASSERT(tree); 824 ASSERT(tree->avl_numnodes == 0); 825 ASSERT(tree->avl_root == NULL); 826 } 827 828 829 /* 830 * Return the number of nodes in an AVL tree. 831 */ 832 ulong_t 833 avl_numnodes(avl_tree_t *tree) 834 { 835 ASSERT(tree); 836 return (tree->avl_numnodes); 837 } 838 839 840 #define CHILDBIT (1L) 841 842 /* 843 * Post-order tree walk used to visit all tree nodes and destroy the tree 844 * in post order. This is used for destroying a tree w/o paying any cost 845 * for rebalancing it. 846 * 847 * example: 848 * 849 * void *cookie = NULL; 850 * my_data_t *node; 851 * 852 * while ((node = avl_destroy_nodes(tree, &cookie)) != NULL) 853 * free(node); 854 * avl_destroy(tree); 855 * 856 * The cookie is really an avl_node_t to the current node's parent and 857 * an indication of which child you looked at last. 858 * 859 * On input, a cookie value of CHILDBIT indicates the tree is done. 860 */ 861 void * 862 avl_destroy_nodes(avl_tree_t *tree, void **cookie) 863 { 864 avl_node_t *node; 865 avl_node_t *parent; 866 int child; 867 void *first; 868 size_t off = tree->avl_offset; 869 870 /* 871 * Initial calls go to the first node or it's right descendant. 872 */ 873 if (*cookie == NULL) { 874 first = avl_first(tree); 875 876 /* 877 * deal with an empty tree 878 */ 879 if (first == NULL) { 880 *cookie = (void *)CHILDBIT; 881 return (NULL); 882 } 883 884 node = AVL_DATA2NODE(first, off); 885 parent = AVL_XPARENT(node); 886 goto check_right_side; 887 } 888 889 /* 890 * If there is no parent to return to we are done. 891 */ 892 parent = (avl_node_t *)((uintptr_t)(*cookie) & ~CHILDBIT); 893 if (parent == NULL) { 894 if (tree->avl_root != NULL) { 895 ASSERT(tree->avl_numnodes == 1); 896 tree->avl_root = NULL; 897 tree->avl_numnodes = 0; 898 } 899 return (NULL); 900 } 901 902 /* 903 * Remove the child pointer we just visited from the parent and tree. 904 */ 905 child = (uintptr_t)(*cookie) & CHILDBIT; 906 parent->avl_child[child] = NULL; 907 ASSERT(tree->avl_numnodes > 1); 908 --tree->avl_numnodes; 909 910 /* 911 * If we just did a right child or there isn't one, go up to parent. 912 */ 913 if (child == 1 || parent->avl_child[1] == NULL) { 914 node = parent; 915 parent = AVL_XPARENT(parent); 916 goto done; 917 } 918 919 /* 920 * Do parent's right child, then leftmost descendent. 921 */ 922 node = parent->avl_child[1]; 923 while (node->avl_child[0] != NULL) { 924 parent = node; 925 node = node->avl_child[0]; 926 } 927 928 /* 929 * If here, we moved to a left child. It may have one 930 * child on the right (when balance == +1). 931 */ 932 check_right_side: 933 if (node->avl_child[1] != NULL) { 934 ASSERT(AVL_XBALANCE(node) == 1); 935 parent = node; 936 node = node->avl_child[1]; 937 ASSERT(node->avl_child[0] == NULL && 938 node->avl_child[1] == NULL); 939 } else { 940 ASSERT(AVL_XBALANCE(node) <= 0); 941 } 942 943 done: 944 if (parent == NULL) { 945 *cookie = (void *)CHILDBIT; 946 ASSERT(node == tree->avl_root); 947 } else { 948 *cookie = (void *)((uintptr_t)parent | AVL_XCHILD(node)); 949 } 950 951 return (AVL_NODE2DATA(node, off)); 952 } 953