1 #include "iwavl.h"
2
3 /*
4 * avl_tree.c - intrusive, nonrecursive AVL tree data structure (self-balancing
5 * binary search tree), implementation file
6 *
7 * Written in 2014-2016 by Eric Biggers <ebiggers3@gmail.com>
8 *
9 * To the extent possible under law, the author(s) have dedicated all copyright
10 * and related and neighboring rights to this software to the public domain
11 * worldwide via the Creative Commons Zero 1.0 Universal Public Domain
12 * Dedication (the "CC0").
13 *
14 * This software is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16 * FOR A PARTICULAR PURPOSE. See the CC0 for more details.
17 *
18 * You should have received a copy of the CC0 along with this software; if not
19 * see <http://creativecommons.org/publicdomain/zero/1.0/>.
20 */
21
22
23 /* Returns the left child (sign < 0) or the right child (sign > 0) of the
24 * specified AVL tree node.
25 * Note: for all calls of this, 'sign' is constant at compilation time,
26 * so the compiler can remove the conditional. */
iwavl_get_child(const struct iwavl_node * parent,int sign)27 IW_INLINE struct iwavl_node* iwavl_get_child(const struct iwavl_node *parent, int sign) {
28 if (sign < 0) {
29 return parent->left;
30 } else {
31 return parent->right;
32 }
33 }
34
iwavl_first_or_last_in_order(const struct iwavl_node * root,int sign)35 IW_INLINE struct iwavl_node* iwavl_first_or_last_in_order(const struct iwavl_node *root, int sign) {
36 const struct iwavl_node *first = root;
37
38 if (first) {
39 while (iwavl_get_child(first, +sign)) {
40 first = iwavl_get_child(first, +sign);
41 }
42 }
43 return (struct iwavl_node*) first;
44 }
45
46 /* Starts an in-order traversal of the tree: returns the least-valued node, or
47 * 0 if the tree is empty. */
iwavl_first_in_order(const struct iwavl_node * root)48 struct iwavl_node* iwavl_first_in_order(const struct iwavl_node *root) {
49 return iwavl_first_or_last_in_order(root, -1);
50 }
51
52 /* Starts a *reverse* in-order traversal of the tree: returns the
53 * greatest-valued node, or 0 if the tree is empty. */
iwavl_last_in_order(const struct iwavl_node * root)54 struct iwavl_node* iwavl_last_in_order(const struct iwavl_node *root) {
55 return iwavl_first_or_last_in_order(root, 1);
56 }
57
iwavl_next_or_prev_in_order(const struct iwavl_node * node,int sign)58 IW_INLINE struct iwavl_node* iwavl_next_or_prev_in_order(const struct iwavl_node *node, int sign) {
59 const struct iwavl_node *next;
60
61 if (iwavl_get_child(node, +sign)) {
62 for (next = iwavl_get_child(node, +sign);
63 iwavl_get_child(next, -sign);
64 next = iwavl_get_child(next, -sign)) {
65 ;
66 }
67 } else {
68 for (next = iwavl_get_parent(node);
69 next && node == iwavl_get_child(next, +sign);
70 node = next, next = iwavl_get_parent(next)) {
71 ;
72 }
73 }
74 return (struct iwavl_node*) next;
75 }
76
77 /* Continues an in-order traversal of the tree: returns the next-greatest-valued
78 * node, or 0 if there is none. */
iwavl_next_in_order(const struct iwavl_node * node)79 struct iwavl_node* iwavl_next_in_order(const struct iwavl_node *node) {
80 return iwavl_next_or_prev_in_order(node, 1);
81 }
82
83 /* Continues a *reverse* in-order traversal of the tree: returns the
84 * previous-greatest-valued node, or 0 if there is none. */
iwavl_prev_in_order(const struct iwavl_node * node)85 struct iwavl_node* iwavl_prev_in_order(const struct iwavl_node *node) {
86 return iwavl_next_or_prev_in_order(node, -1);
87 }
88
89 /* Starts a postorder traversal of the tree. */
iwavl_first_in_postorder(const struct iwavl_node * root)90 struct iwavl_node* iwavl_first_in_postorder(const struct iwavl_node *root) {
91 const struct iwavl_node *first = root;
92
93 if (first) {
94 while (first->left || first->right) {
95 first = first->left ? first->left : first->right;
96 }
97 }
98
99 return (struct iwavl_node*) first;
100 }
101
102 /* Continues a postorder traversal of the tree. @prev will not be deferenced as
103 * it's allowed that its memory has been freed; @prev_parent must be its saved
104 * parent node. Returns 0 if there are no more nodes (i.e. @prev was the
105 * root of the tree). */
iwavl_next_in_postorder(const struct iwavl_node * prev,const struct iwavl_node * prev_parent)106 struct iwavl_node* iwavl_next_in_postorder(
107 const struct iwavl_node *prev,
108 const struct iwavl_node *prev_parent
109 ) {
110 const struct iwavl_node *next = prev_parent;
111
112 if (next && prev == next->left && next->right) {
113 for (next = next->right;
114 next->left || next->right;
115 next = next->left ? next->left : next->right) {
116 ;
117 }
118 }
119 return (struct iwavl_node*) next;
120 }
121
122 /* Sets the left child (sign < 0) or the right child (sign > 0) of the
123 * specified AVL tree node.
124 * Note: for all calls of this, 'sign' is constant at compilation time,
125 * so the compiler can remove the conditional. */
avl_set_child(struct iwavl_node * parent,int sign,struct iwavl_node * child)126 IW_INLINE void avl_set_child(
127 struct iwavl_node *parent, int sign,
128 struct iwavl_node *child
129 ) {
130 if (sign < 0) {
131 parent->left = child;
132 } else {
133 parent->right = child;
134 }
135 }
136
137 /* Sets the parent and balance factor of the specified AVL tree node. */
avl_set_parent_balance(struct iwavl_node * node,struct iwavl_node * parent,int balance_factor)138 IW_INLINE void avl_set_parent_balance(
139 struct iwavl_node *node, struct iwavl_node *parent,
140 int balance_factor
141 ) {
142 node->parent_balance = (uintptr_t) parent | (balance_factor + 1);
143 }
144
145 /* Sets the parent of the specified AVL tree node. */
avl_set_parent(struct iwavl_node * node,struct iwavl_node * parent)146 IW_INLINE void avl_set_parent(struct iwavl_node *node, struct iwavl_node *parent) {
147 node->parent_balance = (uintptr_t) parent | (node->parent_balance & 3);
148 }
149
150 /* Returns the balance factor of the specified AVL tree node --- that is, the
151 * height of its right subtree minus the height of its left subtree. */
avl_get_balance_factor(const struct iwavl_node * node)152 IW_INLINE int avl_get_balance_factor(const struct iwavl_node *node) {
153 return (int) (node->parent_balance & 3) - 1;
154 }
155
156 /* Adds @amount to the balance factor of the specified AVL tree node.
157 * The caller must ensure this still results in a valid balance factor
158 * (-1, 0, or 1). */
avl_adjust_balance_factor(struct iwavl_node * node,int amount)159 IW_INLINE void avl_adjust_balance_factor(struct iwavl_node *node, int amount) {
160 node->parent_balance += amount;
161 }
162
avl_replace_child(struct iwavl_node ** root_ptr,struct iwavl_node * parent,struct iwavl_node * old_child,struct iwavl_node * new_child)163 IW_INLINE void avl_replace_child(
164 struct iwavl_node **root_ptr,
165 struct iwavl_node *parent,
166 struct iwavl_node *old_child,
167 struct iwavl_node *new_child
168 ) {
169 if (parent) {
170 if (old_child == parent->left) {
171 parent->left = new_child;
172 } else {
173 parent->right = new_child;
174 }
175 } else {
176 *root_ptr = new_child;
177 }
178 }
179
180 /*
181 * Template for performing a single rotation ---
182 *
183 * sign > 0: Rotate clockwise (right) rooted at A:
184 *
185 * P? P?
186 * | |
187 * A B
188 * / \ / \
189 * B C? => D? A
190 * / \ / \
191 * D? E? E? C?
192 *
193 * (nodes marked with ? may not exist)
194 *
195 * sign < 0: Rotate counterclockwise (left) rooted at A:
196 *
197 * P? P?
198 * | |
199 * A B
200 * / \ / \
201 * C? B => A D?
202 * / \ / \
203 * E? D? C? E?
204 *
205 * This updates pointers but not balance factors!
206 */
avl_rotate(struct iwavl_node ** const root_ptr,struct iwavl_node * const A,const int sign)207 IW_INLINE void avl_rotate(
208 struct iwavl_node** const root_ptr,
209 struct iwavl_node* const A, const int sign
210 ) {
211 struct iwavl_node* const B = iwavl_get_child(A, -sign);
212 struct iwavl_node* const E = iwavl_get_child(B, +sign);
213 struct iwavl_node* const P = iwavl_get_parent(A);
214
215 avl_set_child(A, -sign, E);
216 avl_set_parent(A, B);
217
218 avl_set_child(B, +sign, A);
219 avl_set_parent(B, P);
220
221 if (E) {
222 avl_set_parent(E, A);
223 }
224
225 avl_replace_child(root_ptr, P, A, B);
226 }
227
228 /*
229 * Template for performing a double rotation ---
230 *
231 * sign > 0: Rotate counterclockwise (left) rooted at B, then
232 * clockwise (right) rooted at A:
233 *
234 * P? P? P?
235 * | | |
236 * A A E
237 * / \ / \ / \
238 * B C? => E C? => B A
239 * / \ / \ / \ / \
240 * D? E B G? D? F?G? C?
241 * / \ / \
242 * F? G? D? F?
243 *
244 * (nodes marked with ? may not exist)
245 *
246 * sign < 0: Rotate clockwise (right) rooted at B, then
247 * counterclockwise (left) rooted at A:
248 *
249 * P? P? P?
250 * | | |
251 * A A E
252 * / \ / \ / \
253 * C? B => C? E => A B
254 * / \ / \ / \ / \
255 * E D? G? B C? G?F? D?
256 * / \ / \
257 * G? F? F? D?
258 *
259 * Returns a pointer to E and updates balance factors. Except for those
260 * two things, this function is equivalent to:
261 * avl_rotate(root_ptr, B, -sign);
262 * avl_rotate(root_ptr, A, +sign);
263 *
264 * See comment in avl_handle_subtree_growth() for explanation of balance
265 * factor updates.
266 */
avl_do_double_rotate(struct iwavl_node ** const root_ptr,struct iwavl_node * const B,struct iwavl_node * const A,const int sign)267 IW_INLINE struct iwavl_node* avl_do_double_rotate(
268 struct iwavl_node** const root_ptr,
269 struct iwavl_node* const B,
270 struct iwavl_node* const A, const int sign
271 ) {
272 struct iwavl_node* const E = iwavl_get_child(B, +sign);
273 struct iwavl_node* const F = iwavl_get_child(E, -sign);
274 struct iwavl_node* const G = iwavl_get_child(E, +sign);
275 struct iwavl_node* const P = iwavl_get_parent(A);
276 const int e = avl_get_balance_factor(E);
277
278 avl_set_child(A, -sign, G);
279 avl_set_parent_balance(A, E, ((sign * e >= 0) ? 0 : -e));
280
281 avl_set_child(B, +sign, F);
282 avl_set_parent_balance(B, E, ((sign * e <= 0) ? 0 : -e));
283
284 avl_set_child(E, +sign, A);
285 avl_set_child(E, -sign, B);
286 avl_set_parent_balance(E, P, 0);
287
288 if (G) {
289 avl_set_parent(G, A);
290 }
291
292 if (F) {
293 avl_set_parent(F, B);
294 }
295
296 avl_replace_child(root_ptr, P, A, E);
297
298 return E;
299 }
300
301 /*
302 * This function handles the growth of a subtree due to an insertion.
303 *
304 * @root_ptr
305 * Location of the tree's root pointer.
306 *
307 * @node
308 * A subtree that has increased in height by 1 due to an insertion.
309 *
310 * @parent
311 * Parent of @node; must not be 0.
312 *
313 * @sign
314 * -1 if @node is the left child of @parent;
315 * +1 if @node is the right child of @parent.
316 *
317 * This function will adjust @parent's balance factor, then do a (single
318 * or double) rotation if necessary. The return value will be %true if
319 * the full AVL tree is now adequately balanced, or %false if the subtree
320 * rooted at @parent is now adequately balanced but has increased in
321 * height by 1, so the caller should continue up the tree.
322 *
323 * Note that if %false is returned, no rotation will have been done.
324 * Indeed, a single node insertion cannot require that more than one
325 * (single or double) rotation be done.
326 */
avl_handle_subtree_growth(struct iwavl_node ** const root_ptr,struct iwavl_node * const node,struct iwavl_node * const parent,const int sign)327 IW_INLINE bool avl_handle_subtree_growth(
328 struct iwavl_node** const root_ptr,
329 struct iwavl_node* const node,
330 struct iwavl_node* const parent,
331 const int sign
332 ) {
333 int old_balance_factor, new_balance_factor;
334
335 old_balance_factor = avl_get_balance_factor(parent);
336
337 if (old_balance_factor == 0) {
338 avl_adjust_balance_factor(parent, sign);
339 /* @parent is still sufficiently balanced (-1 or +1
340 * balance factor), but must have increased in height.
341 * Continue up the tree. */
342 return false;
343 }
344
345 new_balance_factor = old_balance_factor + sign;
346
347 if (new_balance_factor == 0) {
348 avl_adjust_balance_factor(parent, sign);
349 /* @parent is now perfectly balanced (0 balance factor).
350 * It cannot have increased in height, so there is
351 * nothing more to do. */
352 return true;
353 }
354
355 /* @parent is too left-heavy (new_balance_factor == -2) or
356 * too right-heavy (new_balance_factor == +2). */
357
358 /* Test whether @node is left-heavy (-1 balance factor) or
359 * right-heavy (+1 balance factor).
360 * Note that it cannot be perfectly balanced (0 balance factor)
361 * because here we are under the invariant that @node has
362 * increased in height due to the insertion. */
363 if (sign * avl_get_balance_factor(node) > 0) {
364 /* @node (B below) is heavy in the same direction @parent
365 * (A below) is heavy.
366 *
367 * @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
368 * The comment, diagram, and equations below assume sign < 0.
369 * The other case is symmetric!
370 * @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
371 *
372 * Do a clockwise rotation rooted at @parent (A below):
373 *
374 * A B
375 * / \ / \
376 * B C? => D A
377 * / \ / \ / \
378 * D E? F? G?E? C?
379 * / \
380 * F? G?
381 *
382 * Before the rotation:
383 * balance(A) = -2
384 * balance(B) = -1
385 * Let x = height(C). Then:
386 * height(B) = x + 2
387 * height(D) = x + 1
388 * height(E) = x
389 * max(height(F), height(G)) = x.
390 *
391 * After the rotation:
392 * height(D) = max(height(F), height(G)) + 1
393 * = x + 1
394 * height(A) = max(height(E), height(C)) + 1
395 * = max(x, x) + 1 = x + 1
396 * balance(B) = 0
397 * balance(A) = 0
398 */
399 avl_rotate(root_ptr, parent, -sign);
400
401 /* Equivalent to setting @parent's balance factor to 0. */
402 avl_adjust_balance_factor(parent, -sign); /* A */
403
404 /* Equivalent to setting @node's balance factor to 0. */
405 avl_adjust_balance_factor(node, -sign); /* B */
406 } else {
407 /* @node (B below) is heavy in the direction opposite
408 * from the direction @parent (A below) is heavy.
409 *
410 * @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
411 * The comment, diagram, and equations below assume sign < 0.
412 * The other case is symmetric!
413 * @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
414 *
415 * Do a counterblockwise rotation rooted at @node (B below),
416 * then a clockwise rotation rooted at @parent (A below):
417 *
418 * A A E
419 * / \ / \ / \
420 * B C? => E C? => B A
421 * / \ / \ / \ / \
422 * D? E B G? D? F?G? C?
423 * / \ / \
424 * F? G? D? F?
425 *
426 * Before the rotation:
427 * balance(A) = -2
428 * balance(B) = +1
429 * Let x = height(C). Then:
430 * height(B) = x + 2
431 * height(E) = x + 1
432 * height(D) = x
433 * max(height(F), height(G)) = x
434 *
435 * After both rotations:
436 * height(A) = max(height(G), height(C)) + 1
437 * = x + 1
438 * balance(A) = balance(E{orig}) >= 0 ? 0 : -balance(E{orig})
439 * height(B) = max(height(D), height(F)) + 1
440 * = x + 1
441 * balance(B) = balance(E{orig} <= 0) ? 0 : -balance(E{orig})
442 *
443 * height(E) = x + 2
444 * balance(E) = 0
445 */
446 avl_do_double_rotate(root_ptr, node, parent, -sign);
447 }
448
449 /* Height after rotation is unchanged; nothing more to do. */
450 return true;
451 }
452
453 /* Rebalance the tree after insertion of the specified node. */
iwavl_rebalance_after_insert(struct iwavl_node ** root_ptr,struct iwavl_node * inserted)454 void iwavl_rebalance_after_insert(
455 struct iwavl_node **root_ptr,
456 struct iwavl_node *inserted
457 ) {
458 struct iwavl_node *node, *parent;
459 bool done;
460
461 inserted->left = 0;
462 inserted->right = 0;
463
464 node = inserted;
465
466 /* Adjust balance factor of new node's parent.
467 * No rotation will need to be done at this level. */
468
469 parent = iwavl_get_parent(node);
470 if (!parent) {
471 return;
472 }
473
474 if (node == parent->left) {
475 avl_adjust_balance_factor(parent, -1);
476 } else {
477 avl_adjust_balance_factor(parent, +1);
478 }
479
480 if (avl_get_balance_factor(parent) == 0) {
481 /* @parent did not change in height. Nothing more to do. */
482 return;
483 }
484
485 /* The subtree rooted at @parent increased in height by 1. */
486
487 do {
488 /* Adjust balance factor of next ancestor. */
489
490 node = parent;
491 parent = iwavl_get_parent(node);
492 if (!parent) {
493 return;
494 }
495
496 /* The subtree rooted at @node has increased in height by 1. */
497 if (node == parent->left) {
498 done = avl_handle_subtree_growth(root_ptr, node,
499 parent, -1);
500 } else {
501 done = avl_handle_subtree_growth(root_ptr, node,
502 parent, +1);
503 }
504 } while (!done);
505 }
506
507 /*
508 * This function handles the shrinkage of a subtree due to a deletion.
509 *
510 * @root_ptr
511 * Location of the tree's root pointer.
512 *
513 * @parent
514 * A node in the tree, exactly one of whose subtrees has decreased
515 * in height by 1 due to a deletion. (This includes the case where
516 * one of the child pointers has become 0, since we can consider
517 * the "0" subtree to have a height of 0.)
518 *
519 * @sign
520 * +1 if the left subtree of @parent has decreased in height by 1;
521 * -1 if the right subtree of @parent has decreased in height by 1.
522 *
523 * @left_deleted_ret
524 * If the return value is not 0, this will be set to %true if the
525 * left subtree of the returned node has decreased in height by 1,
526 * or %false if the right subtree of the returned node has decreased
527 * in height by 1.
528 *
529 * This function will adjust @parent's balance factor, then do a (single
530 * or double) rotation if necessary. The return value will be 0 if
531 * the full AVL tree is now adequately balanced, or a pointer to the
532 * parent of @parent if @parent is now adequately balanced but has
533 * decreased in height by 1. Also in the latter case, *left_deleted_ret
534 * will be set.
535 */
avl_handle_subtree_shrink(struct iwavl_node ** const root_ptr,struct iwavl_node * parent,const int sign,bool * const left_deleted_ret)536 IW_INLINE struct iwavl_node* avl_handle_subtree_shrink(
537 struct iwavl_node** const root_ptr,
538 struct iwavl_node *parent,
539 const int sign,
540 bool* const left_deleted_ret
541 ) {
542 struct iwavl_node *node;
543 int old_balance_factor, new_balance_factor;
544
545 old_balance_factor = avl_get_balance_factor(parent);
546
547 if (old_balance_factor == 0) {
548 /* Prior to the deletion, the subtree rooted at
549 * @parent was perfectly balanced. It's now
550 * unbalanced by 1, but that's okay and its height
551 * hasn't changed. Nothing more to do. */
552 avl_adjust_balance_factor(parent, sign);
553 return 0;
554 }
555
556 new_balance_factor = old_balance_factor + sign;
557
558 if (new_balance_factor == 0) {
559 /* The subtree rooted at @parent is now perfectly
560 * balanced, whereas before the deletion it was
561 * unbalanced by 1. Its height must have decreased
562 * by 1. No rotation is needed at this location,
563 * but continue up the tree. */
564 avl_adjust_balance_factor(parent, sign);
565 node = parent;
566 } else {
567 /* @parent is too left-heavy (new_balance_factor == -2) or
568 * too right-heavy (new_balance_factor == +2). */
569
570 node = iwavl_get_child(parent, sign);
571
572 /* The rotations below are similar to those done during
573 * insertion (see avl_handle_subtree_growth()), so full
574 * comments are not provided. The only new case is the
575 * one where @node has a balance factor of 0, and that is
576 * commented. */
577
578 if (sign * avl_get_balance_factor(node) >= 0) {
579 avl_rotate(root_ptr, parent, -sign);
580
581 if (avl_get_balance_factor(node) == 0) {
582 /*
583 * @node (B below) is perfectly balanced.
584 *
585 * @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
586 * The comment, diagram, and equations
587 * below assume sign < 0. The other case
588 * is symmetric!
589 * @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
590 *
591 * Do a clockwise rotation rooted at
592 * @parent (A below):
593 *
594 * A B
595 * / \ / \
596 * B C? => D A
597 * / \ / \ / \
598 * D E F? G?E C?
599 * / \
600 * F? G?
601 *
602 * Before the rotation:
603 * balance(A) = -2
604 * balance(B) = 0
605 * Let x = height(C). Then:
606 * height(B) = x + 2
607 * height(D) = x + 1
608 * height(E) = x + 1
609 * max(height(F), height(G)) = x.
610 *
611 * After the rotation:
612 * height(D) = max(height(F), height(G)) + 1
613 * = x + 1
614 * height(A) = max(height(E), height(C)) + 1
615 * = max(x + 1, x) + 1 = x + 2
616 * balance(A) = -1
617 * balance(B) = +1
618 */
619
620 /* A: -2 => -1 (sign < 0)
621 * or +2 => +1 (sign > 0)
622 * No change needed --- that's the same as
623 * old_balance_factor. */
624
625 /* B: 0 => +1 (sign < 0)
626 * or 0 => -1 (sign > 0) */
627 avl_adjust_balance_factor(node, -sign);
628
629 /* Height is unchanged; nothing more to do. */
630 return 0;
631 } else {
632 avl_adjust_balance_factor(parent, -sign);
633 avl_adjust_balance_factor(node, -sign);
634 }
635 } else {
636 node = avl_do_double_rotate(root_ptr, node,
637 parent, -sign);
638 }
639 }
640 parent = iwavl_get_parent(node);
641 if (parent) {
642 *left_deleted_ret = (node == parent->left);
643 }
644 return parent;
645 }
646
647 /* Swaps node X, which must have 2 children, with its in-order successor, then
648 * unlinks node X. Returns the parent of X just before unlinking, without its
649 * balance factor having been updated to account for the unlink. */
avl_tree_swap_with_successor(struct iwavl_node ** root_ptr,struct iwavl_node * X,bool * left_deleted_ret)650 IW_INLINE struct iwavl_node* avl_tree_swap_with_successor(
651 struct iwavl_node **root_ptr,
652 struct iwavl_node *X,
653 bool *left_deleted_ret
654 ) {
655 struct iwavl_node *Y, *ret;
656
657 Y = X->right;
658 if (!Y->left) {
659 /*
660 * P? P? P?
661 * | | |
662 * X Y Y
663 * / \ / \ / \
664 * A Y => A X => A B?
665 * / \ / \
666 * (0) B? (0) B?
667 *
668 * [ X unlinked, Y returned ]
669 */
670 ret = Y;
671 *left_deleted_ret = false;
672 } else {
673 struct iwavl_node *Q;
674
675 do {
676 Q = Y;
677 Y = Y->left;
678 } while (Y->left);
679
680 /*
681 * P? P? P?
682 * | | |
683 * X Y Y
684 * / \ / \ / \
685 * A ... => A ... => A ...
686 * | | |
687 * Q Q Q
688 * / / /
689 * Y X B?
690 * / \ / \
691 * (0) B? (0) B?
692 *
693 *
694 * [ X unlinked, Q returned ]
695 */
696
697 Q->left = Y->right;
698 if (Q->left) {
699 avl_set_parent(Q->left, Q);
700 }
701 Y->right = X->right;
702 avl_set_parent(X->right, Y);
703 ret = Q;
704 *left_deleted_ret = true;
705 }
706
707 Y->left = X->left;
708 avl_set_parent(X->left, Y);
709
710 Y->parent_balance = X->parent_balance;
711 avl_replace_child(root_ptr, iwavl_get_parent(X), X, Y);
712
713 return ret;
714 }
715
716 /*
717 * Removes an item from the specified AVL tree.
718 *
719 * @root_ptr
720 * Location of the AVL tree's root pointer. Indirection is needed
721 * because the root node may change if the tree needed to be rebalanced
722 * because of the deletion or if @node was the root node.
723 *
724 * @node
725 * Pointer to the `struct iwavl_node' embedded in the item to
726 * remove from the tree.
727 *
728 * Note: This function *only* removes the node and rebalances the tree.
729 * It does not free any memory, nor does it do the equivalent of
730 * iwavl_node_set_unlinked().
731 */
iwavl_remove(struct iwavl_node ** root_ptr,struct iwavl_node * node)732 void iwavl_remove(struct iwavl_node **root_ptr, struct iwavl_node *node) {
733 struct iwavl_node *parent;
734 bool left_deleted = false;
735
736 if (node->left && node->right) {
737 /* @node is fully internal, with two children. Swap it
738 * with its in-order successor (which must exist in the
739 * right subtree of @node and can have, at most, a right
740 * child), then unlink @node. */
741 parent = avl_tree_swap_with_successor(root_ptr, node,
742 &left_deleted);
743 /* @parent is now the parent of what was @node's in-order
744 * successor. It cannot be 0, since @node itself was
745 * an ancestor of its in-order successor.
746 * @left_deleted has been set to %true if @node's
747 * in-order successor was the left child of @parent,
748 * otherwise %false. */
749 } else {
750 struct iwavl_node *child;
751
752 /* @node is missing at least one child. Unlink it. Set
753 * @parent to @node's parent, and set @left_deleted to
754 * reflect which child of @parent @node was. Or, if
755 * @node was the root node, simply update the root node
756 * and return. */
757 child = node->left ? node->left : node->right;
758 parent = iwavl_get_parent(node);
759 if (parent) {
760 if (node == parent->left) {
761 parent->left = child;
762 left_deleted = true;
763 } else {
764 parent->right = child;
765 left_deleted = false;
766 }
767 if (child) {
768 avl_set_parent(child, parent);
769 }
770 } else {
771 if (child) {
772 avl_set_parent(child, parent);
773 }
774 *root_ptr = child;
775 return;
776 }
777 }
778
779 /* Rebalance the tree. */
780 do {
781 if (left_deleted) {
782 parent = avl_handle_subtree_shrink(root_ptr, parent,
783 +1, &left_deleted);
784 } else {
785 parent = avl_handle_subtree_shrink(root_ptr, parent,
786 -1, &left_deleted);
787 }
788 } while (parent);
789 }
790