update init() for Lua
[liba.git] / src / avl.c
blobbd24d5656ea52f6fc15146370a5cf043f799c4da
1 #include "a/avl.h"
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)
6 if (parent)
8 if (parent->left == node)
10 parent->left = newnode;
12 else
14 parent->right = newnode;
17 else
19 root->node = 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 */
65 return node->factor;
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:
87 P? P?
88 | |
89 A B
90 / \ / \
91 B C? => D? A
92 / \ / \
93 D? E? E? C?
95 sign < 0: Rotate counterclockwise (left) rooted at A:
97 P? P?
98 | |
99 A B
100 / \ / \
101 C? B => A D?
102 / \ / \
103 E? D? C? E?
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:
128 P? P? P?
129 | | |
130 A A E
131 / \ / \ / \
132 B C? => E C? => B A
133 / \ / \ / \ / \
134 D? E B G? D? F?G? C?
135 / \ / \
136 F? G? D? F?
138 sign < 0: Rotate clockwise (right) rooted at B, then counterclockwise (left) rooted at A:
140 P? P? P?
141 | | |
142 A A E
143 / \ / \ / \
144 C? B => C? E => A B
145 / \ / \ / \ / \
146 E D? G? B C? G?F? D?
147 / \ / \
148 G? F? F? D?
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);
177 return E;
181 This function handles the growth of a subtree due to an insertion.
183 root
184 Location of the tree's root pointer.
186 node
187 A subtree that has increased in height by 1 due to an insertion.
189 parent
190 Parent of node; must not be null.
192 sign
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);
207 if (cur_factor == 0)
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);
211 return A_FALSE;
214 int const new_factor = cur_factor + sign;
215 if (new_factor == 0)
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);
219 return A_TRUE;
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):
237 / \ / \
238 B C? => D A
239 / \ / \ / \
240 D E? F? G?E? C?
242 F? G?
244 Before the rotation:
245 balance(A) = -2
246 balance(B) = -1
247 Let x = height(C). Then:
248 height(B) = x + 2
249 height(D) = x + 1
250 height(E) = x
251 max(height(F), height(G)) = x.
253 After the rotation:
254 height(D) = max(height(F), height(G)) + 1
255 = x + 1
256 height(A) = max(height(E), height(C)) + 1
257 = max(x, x) + 1 = x + 1
258 balance(B) = 0
259 balance(A) = 0
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
269 else
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):
276 A A E
277 / \ / \ / \
278 B C? => E C? => B A
279 / \ / \ / \ / \
280 D? E B G? D? F?G? C?
281 / \ / \
282 F? G? D? F?
284 Before the rotation:
285 balance(A) = -2
286 balance(B) = +1
287 Let x = height(C). Then:
288 height(B) = x + 2
289 height(E) = x + 1
290 height(D) = x
291 max(height(F), height(G)) = x
293 After both rotations:
294 height(A) = max(height(G), height(C)) + 1
295 = x + 1
296 balance(A) = balance(E{orig}) >= 0 ? 0 : -balance(E{orig})
297 height(B) = max(height(D), height(F)) + 1
298 = x + 1
299 balance(B) = balance(E{orig} <= 0) ? 0 : -balance(E{orig})
301 height(E) = x + 2
302 balance(E) = 0
304 a_avl_rotate2(root, node, parent, -sign);
307 /* Height after rotation is unchanged; nothing more to do. */
308 return A_TRUE;
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);
322 else
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. */
332 a_bool done;
333 do {
334 node = parent;
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);
341 else
343 done = a_avl_handle_growth(root, parent, node, +1);
345 } while (!done);
349 This function handles the shrinkage of a subtree due to a deletion.
351 root
352 Location of the tree's root pointer.
354 parent
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.)
359 sign
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.
363 left
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);
376 if (cur_factor == 0)
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);
383 return A_NULL;
386 a_avl_node *node;
387 int const new_factor = cur_factor + sign;
388 if (new_factor == 0)
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);
395 node = parent;
397 else
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):
417 / \ / \
418 B C? => D A
419 / \ / \ / \
420 D E F? G?E C?
422 F? G?
424 Before the rotation:
425 balance(A) = -2
426 balance(B) = 0
427 Let x = height(C). Then:
428 height(B) = x + 2
429 height(D) = x + 1
430 height(E) = x + 1
431 max(height(F), height(G)) = x.
433 After the rotation:
434 height(D) = max(height(F), height(G)) + 1
435 = x + 1
436 height(A) = max(height(E), height(C)) + 1
437 = max(x + 1, x) + 1 = x + 2
438 balance(A) = -1
439 balance(B) = +1
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. */
449 return A_NULL;
451 else
453 a_avl_set_factor(parent, -sign);
454 a_avl_set_factor(node, -sign);
457 else
459 node = a_avl_rotate2(root, node, parent, -sign);
462 parent = a_avl_parent(node);
463 if (parent) { *left = (parent->left == node); }
464 return parent;
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)
473 a_avl_node *node;
475 a_avl_node *Y = X->right;
476 if (!Y->left)
479 P? P? P?
480 | | |
481 X Y Y
482 / \ / \ / \
483 A Y => A X => A B?
484 / \ / \
485 (0) B? (0) B?
487 [ X unlinked, Y returned ]
489 *left = A_FALSE;
490 node = Y;
492 else
494 a_avl_node *Q;
495 do {
496 Q = Y;
497 Y = Y->left;
498 } while (Y->left);
500 P? P? P?
501 | | |
502 X Y Y
503 / \ / \ / \
504 A ... => A ... => A ...
505 | | |
506 Q Q Q
507 / / /
508 Y X B?
509 / \ / \
510 (0) B? (0) B?
512 [ X unlinked, Q returned ]
514 Q->left = Y->right;
515 if (Y->right)
517 a_avl_set_parent(Y->right, Q);
519 Y->right = X->right;
520 a_avl_set_parent(X->right, Y);
521 *left = A_TRUE;
522 node = Q;
525 Y->left = X->left;
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);
536 return node;
539 void a_avl_remove(a_avl *root, a_avl_node *node)
541 a_avl_node *parent;
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),
548 then unlink `node`.
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`.
557 else
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);
566 if (parent)
568 if (parent->left == node)
570 parent->left = child;
571 left = A_TRUE;
573 else
575 parent->right = child;
576 left = A_FALSE;
578 if (child) { a_avl_set_parent(child, parent); }
580 else
582 if (child) { a_avl_set_parent(child, parent); }
583 root->node = child;
584 return;
587 /* Rebalance the tree. */
590 if (left)
592 parent = a_avl_handle_shrink(root, parent, +1, &left);
594 else
596 parent = a_avl_handle_shrink(root, parent, -1, &left);
598 } while (parent);
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;
605 while (*link)
607 parent = *link;
608 int const res = cmp(node, parent);
609 if (res < 0)
611 link = &parent->left;
613 else if (res > 0)
615 link = &parent->right;
617 else { return parent; }
619 *link = a_avl_init(node, parent);
620 a_avl_insert_adjust(root, node);
621 return A_NULL;
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);
629 if (res < 0)
631 cur = cur->left;
633 else if (res > 0)
635 cur = cur->right;
637 else { return cur; }
639 return A_NULL;
642 a_avl_node *a_avl_head(a_avl const *root)
644 a_avl_node *node = root->node;
645 if (node)
647 while (node->left) { node = node->left; }
649 return node;
652 a_avl_node *a_avl_tail(a_avl const *root)
654 a_avl_node *node = root->node;
655 if (node)
657 while (node->right) { node = node->right; }
659 return node;
662 a_avl_node *a_avl_next(a_avl_node *node)
668 / \ / \
669 A C E G
671 if (node->right) /* D -> F -> E */
673 node = node->right;
674 while (node->left) { node = node->left; }
676 else /* C -> B -> D */
678 a_avl_node *leaf;
679 do {
680 leaf = node;
681 node = a_avl_parent(node);
682 } while (node && node->left != leaf);
684 return node;
687 a_avl_node *a_avl_prev(a_avl_node *node)
689 if (node->left)
691 node = node->left;
692 while (node->right) { node = node->right; }
694 else
696 a_avl_node *leaf;
697 do {
698 leaf = node;
699 node = a_avl_parent(node);
700 } while (node && node->right != leaf);
702 return node;
705 a_avl_node *a_avl_pre_next(a_avl_node *node)
711 / \ / \
712 A C E G
714 a_avl_node *leaf;
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)
722 node = node->right;
723 break; /* A -> B -> C */
724 } /* C -> B -> D -> F */
726 return node;
729 a_avl_node *a_avl_pre_prev(a_avl_node *node)
731 a_avl_node *leaf;
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)
739 node = node->left;
740 break;
743 return node;
746 #define A_AVL_POST(head, tail) \
747 for (;;) \
749 if (node->head) \
751 node = node->head; \
753 else if (node->tail) \
755 node = node->tail; \
757 else { break; } \
759 (void)0
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); }
765 return node;
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); }
772 return node;
775 a_avl_node *a_avl_post_next(a_avl_node *node)
781 / \ / \
782 A C E G
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 */
790 } /* C -> B */
791 return node;
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)
800 node = node->left;
801 A_AVL_POST(right, left);
803 return node;
806 a_avl_node *a_avl_tear(a_avl *root, a_avl_node **next)
808 a_avl_node *node = *next;
809 if (!node)
811 node = root->node;
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);
817 return node;