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