• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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