3 /* Replaces the child of the specified AVL tree node. */
4 static A_INLINE
void a_avl_new_child(a_avl
*root
, a_avl_node
*parent
, a_avl_node
*node
, a_avl_node
*newnode
)
8 if (parent
->left
== node
)
10 parent
->left
= newnode
;
14 parent
->right
= newnode
;
23 /* Returns the child of the specified AVL tree node. */
24 static A_INLINE a_avl_node
*a_avl_child(a_avl_node
const *node
, int sign
)
26 return sign
< 0 ? node
->left
: node
->right
;
29 /* Sets the child of the specified AVL tree node. */
30 static A_INLINE
void a_avl_set_child(a_avl_node
*node
, a_avl_node
*child
, int sign
)
32 *(sign
< 0 ? &node
->left
: &node
->right
) = child
;
35 /* Sets the parent and balance factor of the specified AVL tree node. */
36 static A_INLINE
void a_avl_set_parent_factor(a_avl_node
*node
, a_avl_node
*parent
, int factor
)
38 #if defined(A_SIZE_POINTER) && (A_SIZE_POINTER + 0 > 3)
39 node
->parent_
= (a_uptr
)parent
| (a_uptr
)(factor
+ 1);
40 #else /* !A_SIZE_POINTER */
41 node
->parent
= parent
;
42 node
->factor
= factor
;
43 #endif /* A_SIZE_POINTER */
46 /* Sets the parent of the specified AVL tree node. */
47 static A_INLINE
void a_avl_set_parent(a_avl_node
*node
, a_avl_node
*parent
)
49 #if defined(A_SIZE_POINTER) && (A_SIZE_POINTER + 0 > 3)
50 node
->parent_
= (a_uptr
)parent
| (node
->parent_
& 3);
51 #else /* !A_SIZE_POINTER */
52 node
->parent
= parent
;
53 #endif /* A_SIZE_POINTER */
57 Returns the balance factor of the specified AVL tree node --- that is,
58 the height of its right subtree minus the height of its left subtree.
60 static A_INLINE
int a_avl_factor(a_avl_node
const *node
)
62 #if defined(A_SIZE_POINTER) && (A_SIZE_POINTER + 0 > 3)
63 return (int)(node
->parent_
& 3) - 1;
64 #else /* !A_SIZE_POINTER */
66 #endif /* A_SIZE_POINTER */
70 Adds `amount` to the balance factor of the specified AVL tree node.
71 The caller must ensure this still results in a valid balance factor (-1, 0, or 1).
73 static A_INLINE
void a_avl_set_factor(a_avl_node
*node
, int amount
)
75 #if defined(A_SIZE_POINTER) && (A_SIZE_POINTER + 0 > 3)
76 node
->parent_
+= (a_uptr
)amount
;
77 #else /* !A_SIZE_POINTER */
78 node
->factor
+= amount
;
79 #endif /* A_SIZE_POINTER */
83 Template for performing a single rotation (nodes marked with ? may not exist)
85 sign > 0: Rotate clockwise (right) rooted at A:
95 sign < 0: Rotate counterclockwise (left) rooted at A:
105 This updates pointers but not balance factors!
107 static A_INLINE
void a_avl_rotate(a_avl
*root
, a_avl_node
*A
, int sign
)
109 a_avl_node
*const P
= a_avl_parent(A
);
110 a_avl_node
*const B
= a_avl_child(A
, -sign
);
111 a_avl_node
*const E
= a_avl_child(B
, +sign
);
113 a_avl_set_child(A
, E
, -sign
);
114 a_avl_set_parent(A
, B
);
116 a_avl_set_child(B
, A
, +sign
);
117 a_avl_set_parent(B
, P
);
119 if (E
) { a_avl_set_parent(E
, A
); }
120 a_avl_new_child(root
, P
, A
, B
);
124 Template for performing a double rotation (nodes marked with ? may not exist)
126 sign > 0: Rotate counterclockwise (left) rooted at B, then clockwise (right) rooted at A:
138 sign < 0: Rotate clockwise (right) rooted at B, then counterclockwise (left) rooted at A:
150 Returns a pointer to E and updates balance factors. Except for those two things, this function is equivalent to:
152 a_avl_rotate(root, B, -sign);
153 a_avl_rotate(root, A, +sign);
155 static A_INLINE a_avl_node
*a_avl_rotate2(a_avl
*root
, a_avl_node
*B
, a_avl_node
*A
, int sign
)
157 a_avl_node
*const P
= a_avl_parent(A
);
158 a_avl_node
*const E
= a_avl_child(B
, +sign
);
159 a_avl_node
*const F
= a_avl_child(E
, -sign
);
160 a_avl_node
*const G
= a_avl_child(E
, +sign
);
161 int const e
= a_avl_factor(E
);
163 a_avl_set_child(A
, G
, -sign
);
164 a_avl_set_parent_factor(A
, E
, (sign
* e
>= 0) ? 0 : -e
);
166 a_avl_set_child(B
, F
, +sign
);
167 a_avl_set_parent_factor(B
, E
, (sign
* e
<= 0) ? 0 : -e
);
169 a_avl_set_child(E
, A
, +sign
);
170 a_avl_set_child(E
, B
, -sign
);
171 a_avl_set_parent_factor(E
, P
, 0);
173 if (F
) { a_avl_set_parent(F
, B
); }
174 if (G
) { a_avl_set_parent(G
, A
); }
175 a_avl_new_child(root
, P
, A
, E
);
181 This function handles the growth of a subtree due to an insertion.
184 Location of the tree's root pointer.
187 A subtree that has increased in height by 1 due to an insertion.
190 Parent of node; must not be null.
193 -1 if node is the left child of parent;
194 +1 if node is the right child of parent.
196 This function will adjust parent's balance factor, then do a (single or double) rotation if necessary.
197 The return value will be `true` if the full AVL tree is now adequately balanced,
198 or `false` if the subtree rooted at parent is now adequately balanced but has increased in height by 1,
199 so the caller should continue up the tree.
201 Note that if `false` is returned, no rotation will have been done.
202 Indeed, a single node insertion cannot require that more than one (single or double) rotation be done.
204 static A_INLINE a_bool
a_avl_handle_growth(a_avl
*root
, a_avl_node
*parent
, a_avl_node
*node
, int sign
)
206 int const cur_factor
= a_avl_factor(parent
);
209 /* `parent` is still sufficiently balanced (-1 or +1 balance factor), but must have increased in height. Continue up the tree. */
210 a_avl_set_factor(parent
, sign
);
214 int const new_factor
= cur_factor
+ sign
;
217 /* `parent` is now perfectly balanced (0 balance factor). It cannot have increased in height, so there is nothing more to do. */
218 a_avl_set_factor(parent
, sign
);
222 /* `parent` is too left-heavy (new_balance_factor == -2) or too right-heavy (new_balance_factor == +2). */
225 Test whether `node` is left-heavy (-1 balance factor) or right-heavy (+1 balance factor).
226 Note that it cannot be perfectly balanced (0 balance factor) because here we are under the invariant that
227 `node` has increased in height due to the insertion.
229 if (sign
* a_avl_factor(node
) > 0)
232 `node` (B below) is heavy in the same direction `parent` (A below) is heavy.
233 The comment, diagram, and equations below assume sign < 0. The other case is symmetric!
234 Do a clockwise rotation rooted at `parent` (A below):
247 Let x = height(C). Then:
251 max(height(F), height(G)) = x.
254 height(D) = max(height(F), height(G)) + 1
256 height(A) = max(height(E), height(C)) + 1
257 = max(x, x) + 1 = x + 1
261 a_avl_rotate(root
, parent
, -sign
);
263 /* Equivalent to setting `parent`'s balance factor to 0. */
264 a_avl_set_factor(parent
, -sign
); // A
266 /* Equivalent to setting `node`'s balance factor to 0. */
267 a_avl_set_factor(node
, -sign
); // B
272 `node` (B below) is heavy in the direction opposite from the direction `parent` (A below) is heavy.
273 The comment, diagram, and equations below assume sign < 0. The other case is symmetric!
274 Do a counterblockwise rotation rooted at `node` (B below), then a clockwise rotation rooted at `parent` (A below):
287 Let x = height(C). Then:
291 max(height(F), height(G)) = x
293 After both rotations:
294 height(A) = max(height(G), height(C)) + 1
296 balance(A) = balance(E{orig}) >= 0 ? 0 : -balance(E{orig})
297 height(B) = max(height(D), height(F)) + 1
299 balance(B) = balance(E{orig} <= 0) ? 0 : -balance(E{orig})
304 a_avl_rotate2(root
, node
, parent
, -sign
);
307 /* Height after rotation is unchanged; nothing more to do. */
311 void a_avl_insert_adjust(a_avl
*root
, a_avl_node
*node
)
313 /* Adjust balance factor of new node's parent. No rotation will need to be done at this level. */
315 a_avl_node
*parent
= a_avl_parent(node
);
316 if (!parent
) { return; }
318 if (parent
->left
== node
)
320 a_avl_set_factor(parent
, -1);
324 a_avl_set_factor(parent
, +1);
327 /* `parent` did not change in height. Nothing more to do. */
328 if (a_avl_factor(parent
) == 0) { return; }
330 /* The subtree rooted at parent increased in height by 1. */
335 parent
= a_avl_parent(node
);
336 if (!parent
) { return; }
337 if (parent
->left
== node
)
339 done
= a_avl_handle_growth(root
, parent
, node
, -1);
343 done
= a_avl_handle_growth(root
, parent
, node
, +1);
349 This function handles the shrinkage of a subtree due to a deletion.
352 Location of the tree's root pointer.
355 A node in the tree, exactly one of whose subtrees has decreased in height by 1 due to a deletion.
356 (This includes the case where one of the child pointers has become null,
357 since we can consider the "null" subtree to have a height of 0.)
360 +1 if the left subtree of parent has decreased in height by 1;
361 -1 if the right subtree of parent has decreased in height by 1.
364 If the return value is not null, this will be set to
365 `true` if the left subtree of the returned node has decreased in height by 1,
366 `false` if the right subtree of the returned node has decreased in height by 1.
368 This function will adjust parent's balance factor, then do a (single or double) rotation if necessary.
369 The return value will be null if the full AVL tree is now adequately balanced,
370 or a pointer to the parent of parent if parent is now adequately balanced but has decreased in height by 1.
371 Also in the latter case, *left will be set.
373 static A_INLINE a_avl_node
*a_avl_handle_shrink(a_avl
*root
, a_avl_node
*parent
, int sign
, a_bool
*left
)
375 int const cur_factor
= a_avl_factor(parent
);
379 Prior to the deletion, the subtree rooted at `parent` was perfectly balanced.
380 It's now unbalanced by 1, but that's okay and its height hasn't changed. Nothing more to do.
382 a_avl_set_factor(parent
, sign
);
387 int const new_factor
= cur_factor
+ sign
;
391 The subtree rooted at `parent` is now perfectly balanced, whereas before the deletion it was unbalanced by 1.
392 Its height must have decreased by 1. No rotation is needed at this location, but continue up the tree.
394 a_avl_set_factor(parent
, sign
);
399 /* `parent` is too left-heavy (new_factor == -2) or too right-heavy (new_factor == +2). */
400 node
= a_avl_child(parent
, sign
);
403 The rotations below are similar to those done during insertion, so full comments are not provided.
404 The only new case is the one where `node` has a balance factor of 0, and that is commented.
406 if (sign
* a_avl_factor(node
) >= 0)
408 a_avl_rotate(root
, parent
, -sign
);
409 if (a_avl_factor(node
) == 0)
412 `node` (B below) is perfectly balanced.
413 The comment, diagram, and equations below assume sign < 0. The other case is symmetric!
414 Do a clockwise rotation rooted at `parent` (A below):
427 Let x = height(C). Then:
431 max(height(F), height(G)) = x.
434 height(D) = max(height(F), height(G)) + 1
436 height(A) = max(height(E), height(C)) + 1
437 = max(x + 1, x) + 1 = x + 2
441 A: -2 => -1 (sign < 0) or +2 => +1 (sign > 0)
442 No change needed --- that's the same as cur_factor.
444 B: 0 => +1 (sign < 0) or 0 => -1 (sign > 0)
446 a_avl_set_factor(node
, -sign
);
448 /* Height is unchanged; nothing more to do. */
453 a_avl_set_factor(parent
, -sign
);
454 a_avl_set_factor(node
, -sign
);
459 node
= a_avl_rotate2(root
, node
, parent
, -sign
);
462 parent
= a_avl_parent(node
);
463 if (parent
) { *left
= (parent
->left
== node
); }
468 Swaps node X, which must have 2 children, with its in-order successor, then unlinks node X.
469 Returns the parent of X just before unlinking, without its balance factor having been updated to account for the unlink.
471 static A_INLINE a_avl_node
*a_avl_handle_remove(a_avl
*root
, a_avl_node
*X
, a_bool
*left
)
475 a_avl_node
*Y
= X
->right
;
487 [ X unlinked, Y returned ]
504 A ... => A ... => A ...
512 [ X unlinked, Q returned ]
517 a_avl_set_parent(Y
->right
, Q
);
520 a_avl_set_parent(X
->right
, Y
);
526 a_avl_set_parent(X
->left
, Y
);
528 #if defined(A_SIZE_POINTER) && (A_SIZE_POINTER + 0 > 3)
529 Y
->parent_
= X
->parent_
;
530 #else /* !A_SIZE_POINTER */
531 Y
->parent
= X
->parent
;
532 Y
->factor
= X
->factor
;
533 #endif /* A_SIZE_POINTER */
534 a_avl_new_child(root
, a_avl_parent(X
), X
, Y
);
539 void a_avl_remove(a_avl
*root
, a_avl_node
*node
)
542 a_bool left
= A_FALSE
;
543 if (node
->left
&& node
->right
)
546 `node` is fully internal, with two children. Swap it with its in-order successor
547 (which must exist in the right subtree of `node` and can have, at most, a right child),
550 parent
= a_avl_handle_remove(root
, node
, &left
);
552 `parent` is now the parent of what was `node`'s in-order successor.
553 It cannot be null, since `node` itself was an ancestor of its in-order successor.
554 `left` has been set to `true` if `node`'s in-order successor was the left child of `parent`, otherwise `false`.
559 a_avl_node
*const child
= node
->left
? node
->left
: node
->right
;
561 `node` is missing at least one child. Unlink it. Set `parent` to `node`'s parent,
562 and set `left` to reflect which child of `parent` `node` was.
563 Or, if `node` was the root node, simply update the root node and return.
565 parent
= a_avl_parent(node
);
568 if (parent
->left
== node
)
570 parent
->left
= child
;
575 parent
->right
= child
;
578 if (child
) { a_avl_set_parent(child
, parent
); }
582 if (child
) { a_avl_set_parent(child
, parent
); }
587 /* Rebalance the tree. */
592 parent
= a_avl_handle_shrink(root
, parent
, +1, &left
);
596 parent
= a_avl_handle_shrink(root
, parent
, -1, &left
);
601 a_avl_node
*a_avl_insert(a_avl
*root
, a_avl_node
*node
, int (*cmp
)(void const *, void const *))
603 a_avl_node
*parent
= root
->node
;
604 a_avl_node
**link
= &root
->node
;
608 int const res
= cmp(node
, parent
);
611 link
= &parent
->left
;
615 link
= &parent
->right
;
617 else { return parent
; }
619 *link
= a_avl_init(node
, parent
);
620 a_avl_insert_adjust(root
, node
);
624 a_avl_node
*a_avl_search(a_avl
const *root
, void const *ctx
, int (*cmp
)(void const *, void const *))
626 for (a_avl_node
*cur
= root
->node
; cur
;)
628 int const res
= cmp(ctx
, cur
);
642 a_avl_node
*a_avl_head(a_avl
const *root
)
644 a_avl_node
*node
= root
->node
;
647 while (node
->left
) { node
= node
->left
; }
652 a_avl_node
*a_avl_tail(a_avl
const *root
)
654 a_avl_node
*node
= root
->node
;
657 while (node
->right
) { node
= node
->right
; }
662 a_avl_node
*a_avl_next(a_avl_node
*node
)
671 if (node
->right
) /* D -> F -> E */
674 while (node
->left
) { node
= node
->left
; }
676 else /* C -> B -> D */
681 node
= a_avl_parent(node
);
682 } while (node
&& node
->left
!= leaf
);
687 a_avl_node
*a_avl_prev(a_avl_node
*node
)
692 while (node
->right
) { node
= node
->right
; }
699 node
= a_avl_parent(node
);
700 } while (node
&& node
->right
!= leaf
);
705 a_avl_node
*a_avl_pre_next(a_avl_node
*node
)
715 if (node
->left
) { return node
->left
; }
716 if (node
->right
) { return node
->right
; }
717 for (leaf
= node
, node
= a_avl_parent(node
); node
;
718 leaf
= node
, node
= a_avl_parent(node
))
720 if (node
->right
&& node
->right
!= leaf
)
723 break; /* A -> B -> C */
724 } /* C -> B -> D -> F */
729 a_avl_node
*a_avl_pre_prev(a_avl_node
*node
)
732 if (node
->right
) { return node
->right
; }
733 if (node
->left
) { return node
->left
; }
734 for (leaf
= node
, node
= a_avl_parent(node
); node
;
735 leaf
= node
, node
= a_avl_parent(node
))
737 if (node
->left
&& node
->left
!= leaf
)
746 #define A_AVL_POST(head, tail) \
753 else if (node->tail) \
761 a_avl_node
*a_avl_post_head(a_avl
const *root
)
763 a_avl_node
*node
= root
->node
;
764 if (node
) { A_AVL_POST(left
, right
); }
768 a_avl_node
*a_avl_post_tail(a_avl
const *root
)
770 a_avl_node
*node
= root
->node
;
771 if (node
) { A_AVL_POST(right
, left
); }
775 a_avl_node
*a_avl_post_next(a_avl_node
*node
)
784 a_avl_node
*leaf
= node
;
785 node
= a_avl_parent(node
);
786 if (node
&& node
->right
&& node
->right
!= leaf
)
788 node
= node
->right
; /* B -> D -> F -> E */
789 A_AVL_POST(left
, right
); /* A -> B -> C */
794 a_avl_node
*a_avl_post_prev(a_avl_node
*node
)
796 a_avl_node
*leaf
= node
;
797 node
= a_avl_parent(node
);
798 if (node
&& node
->left
&& node
->left
!= leaf
)
801 A_AVL_POST(right
, left
);
806 a_avl_node
*a_avl_tear(a_avl
*root
, a_avl_node
**next
)
808 a_avl_node
*node
= *next
;
812 if (!node
) { return node
; }
814 A_AVL_POST(left
, right
);
815 *next
= a_avl_parent(node
);
816 a_avl_new_child(root
, *next
, node
, A_NULL
);