5 * (c) 2024 Straylight/Edgeware
8 /*----- Licensing notice --------------------------------------------------*
10 * This file is part of Xyla, a library of binary trees.
12 * Xyla is free software: you can redistribute it and/or modify it under
13 * the terms of the GNU Lesser General Public License as published by the
14 * Free Software Foundation; either version 3 of the License, or (at your
15 * option) any later version.
17 * Xyla is distributed in the hope that it will be useful, but WITHOUT
18 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
20 * License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with Xyla. If not, see <https://www.gnu.org/licenses/>.
29 /*----- Header files ------------------------------------------------------*/
33 /*----- Data structures ---------------------------------------------------*/
35 struct xyla_avl_nodeslots {
37 #define XYLA_AVLF_BALMASK 3u
38 #define XYLA_AVLBAL_LBIAS 1u
39 #define XYLA_AVLBAL_EVEN 0u
40 #define XYLA_AVLBAL_RBIAS 2u
42 #define XYLA_AVL_NODEPFX XYLA_BT_NODEPFX; struct xyla_avl_nodeslots avl
43 struct xyla_avl_node { XYLA_AVL_NODEPFX; };
44 #define XYLA_AVL_NODEUSFX struct xyla_avl_node avl; XYLA_BT_NODEUSFX
45 union xyla_avl_nodeu { XYLA_AVL_NODEUSFX; };
47 /* The maximum possible height H_n for an AVL tree containing n nodes is
48 * somewhat annoying to calculate. The best way to start is to reverse the
49 * question and find the smallest number N_h of nodes which can force the
50 * tree to have height h.
52 * This is going to involve a recurrence. The base case is the rather
53 * unsurprising observations that N_0 = 0 and N_1 = 1.
55 * The imbalance between the root's left and right subtrees can be at most 1.
56 * The cheapest way we can make a tree with height h, then, is if the root is
57 * biased to the left (say) and then its left and right subtrees are the
58 * smallest trees with height h - 1 and h - 2 respectively. We have the
59 * oddly familiar recurrence
61 * N_h = N_{h-1} + N_{h-2} + 1 .
63 * Guess that N_h = x^h + C for some constants x and C. Then
65 * x^h + C = x^{h-1} + x^{h-2} + 2 C + 1 ,
69 * x^h = x^{h-1} + x^{h-2} + C + 1 ,
71 * so setting C = -1 seems like the best bet; that leaves
73 * x^h = x^{h-1} + x^{h-2} ,
75 * which is well-known to be solved by setting x = φ or x = φ̄, where
78 * φ = ------ and φ̄ = ------ .
81 * This relationship clearly holds for any linear combination of φ and φ̄. So
84 * N_h = A φ^h + B φ̄^h - 1
86 * and check the initial conditions: N_0 = 0 forces A + B = 1; and N_1 = 1
91 * substituting φ and φ̄ and rearranging gives
93 * (A + B) + √5 (A - B) = 4 .
95 * We know A + B = 1, so A - B = 3/√5 = 3 √5/5. Adding these two gives
98 * A = -------- and B = -------- .
101 * What we actually wanted to know was the maximum possible height H_n for an
102 * AVL tree with n nodes. Suppose, then, that, for some h, the tree has
103 * n >= N_h >= A φ^h + B φ̄^h - 1 nodes. Notice that |B < 1 and |φ̄| < 1;
104 * therefore, |B φ̄^h| < 1, and we have n >= A φ^h - 2. (Sadly, φ̄ is
107 * Continuing, we see A φ^h <= n + 2. Taking (binary) logs gives h lg φ +
108 * lg A <= lg (n + 2), whence
111 * h <= ----------------- .
114 * This is pretty gnarly to evaluate with the C preprocessor. Fortunately,
115 * 0 < 13/9 - 1/lg φ < 1/200, so
118 * h <= -- lg (n + 2) - ---- .
121 * In fact, we can do better. As n gets larger, the difference lg (n + 2) -
122 * lg n tends to zero. There is therefore a value N such that
124 * 13 lg (n + 2) - lg A
125 * -- lg n <= -----------------
130 * This is too horrid to solve by hand, but numerical methods show that
131 * N = 12 satisfies our requirements. We must, of course, round up rather
132 * than down while computing this.
134 * Our n of interest is the largest value that can fit in `size_t', which is
135 * an unsigned type; therefore n = 2^k - 1 for some k, and ⌊lg (n + 2)⌋ = k.
136 * Alas, C doesn't give us k directly, but it can certainly be no more than
137 * `CHAR_BIT*sizeof(size_t)'; since padding bits in integers are extremely
138 * rare, this is usually the exact value. C permits objects at least
139 * 2^{15} - 1 bytes in size, so this must be at least that large. In
140 * particular, it's larger than 12, so we can apply this simplification.
142 * On conventional 32-bit targets, this is 47; on 64-bit targets, it's 93.
143 * Both overestimate by one entry.
146 #define XYLA_AVL_HTMAX (13*(sizeof(size_t)*CHAR_BIT + 8)/9)
148 struct xyla_avl_iter {
150 const struct xyla_bt_node *stack[XYLA_AVL_HTMAX];
152 struct xyla_avl_riter {
154 const struct xyla_bt_node *stack[XYLA_AVL_HTMAX];
157 struct xyla_avl_path {
159 struct xyla_bt_node **p[XYLA_AVL_HTMAX + 1];
162 /*----- Miscellaneous utilities -------------------------------------------*/
164 extern int xyla_avl_height(const struct xyla_avl_node */*node*/);
165 /* Return the height for the (sub)tree rooted at NODE. This is primarily
166 * useful as input to `xyla_avl_join' and `xyla_avl_split'.
169 /*----- Iteration ---------------------------------------------------------*/
171 extern void xyla_avl_inititer(const struct xyla_bt_node */*root*/,
172 struct xyla_avl_iter */*it*/);
173 /* Initialize the iterator IT to start returning nodes in left-to-right
174 * order from the tree rooted at ROOT.
177 extern void *xyla_avl_next(struct xyla_avl_iter */*it*/);
178 /* Advance the iterator IT, returning the next node, or null if the
179 * iteration is complete.
181 * Inserting or removing elements invalidates the iterator. As a special
182 * exception, it is permitted to free all of the nodes by iterating over
183 * the tree in the obvious manner:
185 * xyla_avl_inititer(tree, &it);
187 * node = xyla_avl_next(&it); if (!node) break;
191 * It's probably better to use `xyla_bt_severfirst' for this task.
194 extern void xyla_avl_initriter(const struct xyla_bt_node */*root*/,
195 struct xyla_avl_riter */*rit*/);
196 /* Initialize the iterator RIT to start returning nodes in right-to-left
197 * order from the tree rooted at ROOT.
200 extern void *xyla_avl_prev(struct xyla_avl_riter */*rit*/);
201 /* Advance the iterator RIT, returning the previous node, or null if the
202 * iteration is complete.
204 * Inserting or removing elements invalidates the iterator. As a special
205 * exception, it is permitted to free all of the nodes by iterating over
206 * the tree in the obvious manner:
208 * xyla_avl_inititer(tree, &rit);
210 * node = xyla_avl_next(&rit); if (!node) break;
214 * It's probably better to use `xyla_bt_severfirst' for this task.
217 /*----- Paths -------------------------------------------------------------*/
219 extern void *xyla_avl_current(const struct xyla_avl_path */*path*/);
220 /* Return the node currently designated by PATH, or null if PATH is
224 extern void xyla_avl_copypath(struct xyla_avl_path */*newpath*/,
225 const struct xyla_avl_path */*path*/);
226 /* Make a copy of PATH as NEWPATH. This has the same effect as simply
227 * assigning the path structures, but may be significantly faster because
228 * it only copies the active part of the path vector.
231 extern void *xyla_avl_firstpath(struct xyla_bt_node **/*root*/,
232 struct xyla_avl_path */*path*/);
233 extern void *xyla_avl_lastpath(struct xyla_bt_node **/*root*/,
234 struct xyla_avl_path */*path*/);
235 /* Return the first or last node in the tree, together with a PATH to the
236 * requested node, which can be used to remove them, or to navigate to
237 * other nodes in the tree. Return null if the tree is empty.
240 extern void *xyla_avl_nextpath(struct xyla_avl_path */*path*/);
241 extern void *xyla_avl_prevpath(struct xyla_avl_path */*path*/);
242 /* Return the next or previous node in the tree, and update the PATH to the
243 * requested node, which can be used to remove them, or to navigate to
244 * other nodes in the tree.
246 * If the path is full, i.e., refers to an existing node, then the
247 * functions return that node's successor or predecessor. If the path is
248 * empty, i.e., refers to a space between nodes where a new node can be
249 * inserted, then the functions return the node at the upper or lower end
250 * of the gap, unless the `gap' is actually at an extreme of the tree and
251 * no such node exists. In the latter case, a null pointer is returned.
252 * The path is modified to refer to the new node, if any, or to the gap at
253 * the appropriate extreme of the tree.
256 extern void xyla_avl_beforepath(struct xyla_avl_path */*path*/);
257 extern void xyla_avl_afterpath(struct xyla_avl_path */*path*/);
258 /* Advance the PATH to just before or after the current node. The path
259 * thereby becomes empty, suitable to insert an element or split the tree
260 * just before or after the previously selected node.
263 extern void *xyla_avl_rootpath(struct xyla_bt_node **/*root*/,
264 struct xyla_avl_path */*path*/);
265 /* Initialize PATH to refer to the tree root, given the address ROOT of the
266 * root link, and return this root node. The resulting path will be empty
267 * if and only if the tree is empty.
270 extern void *xyla_avl_uppath(unsigned */*pos_out*/,
271 struct xyla_avl_path */*path*/);
272 /* Update the PATH to refer to the parent of the link currently designated;
273 * return this parent node, and set *POS_OUT to the `XYLA_BTPOS_...'
274 * constant describing the link's relation to the parent. If the path
275 * initially designated the tree's root link, then return null, set
276 * *POS_OUT to `XYLA_BTPOS_ROOT', and leave the path unchanged; otherwise,
277 * the tree becomes full.
280 extern void *xyla_avl_leftpath(struct xyla_avl_path */*path*/);
281 extern void *xyla_avl_rightpath(struct xyla_avl_path */*path*/);
282 /* Update the PATH to refer to the left or right child of the node
283 * currently designated, and set NODE to be this child node. The PATH must
284 * initially have been full, and may become empty as a result.
287 extern void xyla_avl_replace(const struct xyla_avl_path */*path*/,
288 struct xyla_avl_node */*node*/);
289 /* Replace the node identified by the PATH with the given NODE. The node's
290 * links need not be initialized. Paths and iterators are not invalidated.
291 * It is the caller's responsibility to ensure that any ordering invariants
292 * are respected as a result of the change.
295 extern void xyla_avl_ripple(struct xyla_bt_nodecls */*cls*/,
296 const struct xyla_avl_path */*path*/);
297 /* Update a node's ancestors -- i.e., call the node class `upd' function on
298 * them, in ascending order -- after it has been modified. The PATH
299 * describes a full path to the node that has been changed. The PATH
303 extern int xyla_avl_ascend(xyla_bt_ascendfn */*fn*/,
304 const struct xyla_avl_path */*path*/,
306 /* Ascend the tree along the PATH, allowing FN to accumulate summary data
307 * from the nodes to the root; see `XYLA_BT_ASCEND' for details. If FN
308 * returns nonzero, then stop and return the nonzero value; otherwise
309 * return zero. The PATH remains valid.
312 /*----- Searching ---------------------------------------------------------*/
314 extern void *xyla_avl_lookup(struct xyla_bt_nodecls */*cls*/,
315 struct xyla_bt_node **/*root*/,
316 xyla_bt_navfn */*navfn*/, void */*arg*/);
317 /* Search for a node within the tree rooted at ROOT. The search is guided
318 * by NAVFN, passing it ARG at each node. Return the node that the
319 * function matches, or null if no matching node exists.
322 extern void *xyla_avl_probe(struct xyla_bt_nodecls */*cls*/,
323 struct xyla_bt_node **/*root*/,
324 xyla_bt_navfn */*navfn*/, void */*arg*/,
325 struct xyla_avl_path */*path*/);
326 /* Search for a node within the tree rooted at ROOT. The search is guided
327 * by NAVFN, passing it ARG at each node. Record the search path in PATH.
328 * This can be used later, e.g., by `xyla_avl_insert' to insert a new node
329 * if none was found, or by `xyla_avl_remove' to remove the node that was
330 * found. Return the node that the function matches, or null if no
331 * matching node exists.
334 /*----- Insertion and removal ---------------------------------------------*/
336 extern int xyla_avl_insert(struct xyla_bt_nodecls */*cls*/,
337 struct xyla_avl_path */*path*/,
338 struct xyla_avl_node */*node*/);
339 /* Add a new node to the tree, in the place determined by the empty PATH.
340 * It's the caller's responsibility to ensure that inserting the node here
341 * respects any ordering invariants. Returns `XYLA_RC_HTCHG' if the tree
342 * has increased in height, or `XYLA_RC_OK' if its height remains
345 * The new node is not copied, and its storage must remain valid until the
346 * node is removed or the tree is discarded.
349 extern int xyla_avl_remove(struct xyla_bt_nodecls */*cls*/,
350 struct xyla_avl_path */*path*/);
351 /* Remove the node identified by the PATH. The node was allocated by the
352 * caller, and should be freed by the caller in whatever way is
353 * appropriate. Returns `XYLA_RC_HTCHG' if the tree has decreased in
354 * height, or `XYLA_RC_OK' if its height remains unchanged.
357 /*----- Splitting and joining ---------------------------------------------*/
359 extern int xyla_avl_join(struct xyla_bt_nodecls */*cls*/,
360 struct xyla_bt_node **/*root_out*/,
362 struct xyla_bt_node **/*left*/, int /*lht*/,
363 struct xyla_bt_node */*mid*/,
364 struct xyla_bt_node **/*right*/, int /*rht*/);
365 /* Concatenate the two trees rooted at LEFT and RIGHT in order; if MID is
366 * not null, then place this node between them. The root of the resulting
367 * tree is stored in *ROOT_OUT. It's the caller's responsibility to ensure
368 * that this respects any ordering invariants.
370 * If the heights of the LEFT and RIGHT trees are known, then they can be
371 * passed in as LHT and RHT; otherwise, LHT and/or RHT must be -1. The
372 * height of the combined tree is stored in *ROOTHT_OUT if this is not
375 * The ROOT_OUT pointer may equal either LEFT or RIGHT (or, indeed, both,
376 * only if both are empty). If LEFT is distinct from ROOT_OUT then *LEFT
377 * is set null on exit; similarly, if RIGHT is distinct from ROOT_OUT, then
378 * *RIGHT is set null on exit.
380 * Returns `XYLA_RC_OK'.
383 extern int xyla_avl_split(struct xyla_bt_nodecls */*cls*/,
384 struct xyla_bt_node **/*left_out*/,
386 struct xyla_bt_node **/*mid_out*/,
387 struct xyla_bt_node **/*right_out*/,
389 struct xyla_avl_path */*path*/);
390 /* Split a tree tree into two at the indicated place indicated by the PATH.
391 * Store in *LEFT_OUT and *RIGHT_OUT the roots of trees containing every
392 * node respectively preceding and following the PATH, and in *LHT_OUT and
393 * *RHT_OUT the heights of the respective output trees; either or both of
394 * LHT_OUT and RHT_OUT may be null to discard this information.
396 * If the PATH is full, i.e., it denotes a node in the input tree, then
397 * that becomes the `middle node', which does not appear in either output
398 * tree; a pointer to this node is stored in *MID_OUT.
400 * Returns `XYLA_RC_OK'.
403 extern int xyla_avl_splitat(struct xyla_bt_nodecls */*cls*/,
404 struct xyla_bt_node **/*left_out*/,
406 struct xyla_bt_node **/*mid_out*/,
407 struct xyla_bt_node **/*right_out*/,
409 struct xyla_bt_node **/*root*/,
410 const void */*key*/);
411 /* Split the tree rooted at ROOT into two at an indicated KEY. Store in
412 * *LEFT_OUT and *RIGHT_OUT the roots of trees containing every node whose
413 * key is respectively less than and greater than the KEY, and in *LHT_OUT
414 * and *RHT_OUT the heights of the respective output trees; either or both
415 * of LHT_OUT and RHT_OUT may be null to discard this information.
417 * If a node matching the KEY exists in the input tree, then that becomes
418 * the `middle node', which does not appear in either output tree; a
419 * pointer to this node is stored in *MID_OUT.
421 * This operation assumes that the tree traversal ordering matches an
422 * ordering on search keys, which is implemented by the node-class `nav'
425 * Returns `XYLA_RC_OK'.
428 extern int xyla_avl_splitroot(struct xyla_bt_node **/*left_out*/,
430 struct xyla_bt_node **/*root_out*/,
431 struct xyla_bt_node **/*right_out*/,
433 struct xyla_bt_node **/*root*/, int /*ht*/);
434 /* Split the tree rooted at ROOT into two at its root. Store in *ROOT_OUT
435 * a pointer to the original root node, or null if the tree was initially
436 * empty; store in *LEFT_OUT and *RIGHT_OUT the root of the original root's
437 * left and right subtrees respectively, and in *LHT_OUT and *RHT_OUT the
438 * heights of the respective output trees; either or both of LHT_OUT and
439 * RHT_OUT may be null to discard this information. If the initial tree
440 * height is known, it can be passed in as HT; otherwise, HT must be -1.
442 * Returns `XYLA_RC_OK'.
445 /*----- Set operations ----------------------------------------------------*/
447 extern int xyla_avl_unisect(struct xyla_bt_nodecls */*cls*/,
448 struct xyla_bt_node **/*uni_out*/,
450 struct xyla_bt_node **/*isect_out*/,
451 int */*isectht_out*/,
452 struct xyla_bt_node **/*aroot*/, int /*aht*/,
453 struct xyla_bt_node **/*broot*/, int /*bht*/);
454 /* Compute the union and intersection of two trees.
456 * On entry, *AROOT and *BROOT are the roots of two trees a and b, with
457 * their respective heights in AHT and BHT, if the caller knows them, or -1
458 * otherwise. The trees are considered to represent sets, with one element
459 * per node; the element is determined by the `key' node-class operation.
460 * On exit, *UNI_OUT points to the root of a tree containing (one copy of)
461 * each element present in either a or b, and *ISECT_OUT points to the root
462 * of a tree containing the other copy of each element present in both a
463 * and b; the heights of the output trees are stored in *UNIHT_OUT and
464 * *ISECTHT_OUT, if these are not null. If AROOT and/or BROOT are distinct
465 * from UNI_OUT and ISECT_OUT, then null pointers are stored in them. The
466 * original trees are destroyed; each node in the original operands trees
467 * ends up in exactly one of the result trees.
469 * Returns `XYLA_RC_OK'.
472 extern int xyla_avl_diffsect(struct xyla_bt_nodecls */*cls*/,
473 struct xyla_bt_node **/*diff_out*/,
475 struct xyla_bt_node **/*isect_out*/,
476 int */*isectht_out*/,
477 struct xyla_bt_node **/*aroot*/, int /*aht*/,
478 struct xyla_bt_node **/*broot*/);
479 /* Compute the set difference of the two operand trees.
481 * On entry, *AROOT and *BROOT are the roots of two trees a and b, with a's
482 * height in AHT, if the caller knows it, or -1 otherwise (the height of b
483 * is not significant). The trees are considered to represent sets, with
484 * one element per node; the element is determined by the `key' node-class
485 * operation. On exit, *DIFF_OUT points to the root of a tree containing
486 * each element of a but not b, and *ISECT_OUT points to the root of a tree
487 * containing each element of a that's also in b; the heights of the output
488 * trees are stored in *DIFFHT_OUT and *ISECTHT_OUT, if these are not null.
489 * If AROOT and/or BROOT are distinct from DIFF_OUT and ISECT_OUT, then
490 * null pointers are stored in them. The original a tree is destroyed;
491 * each node in the original operands trees ends up in exactly one of the
492 * result trees. The input b tree is unchanged.
494 * Returns `XYLA_RC_OK'.
497 /*----- Checking ----------------------------------------------------------*/
499 #ifndef XYLA_FREESTANDING
501 extern int xyla_avl_check(struct xyla_bt_nodecls */*cls*/,
502 struct xyla_bt_node *const */*root*/,
503 FILE */*fp*/, unsigned /*f*/,
504 int /*expht*/, void */*arg*/);
505 /* Examine an AVL tree, checking that it satisfies all of the necessary
506 * invariants. If EXPHT is not equal to -1, then check that the overall
507 * tree height is equal to EXPHT.
509 * This function uses the `xyla_bt_check' framework; see the description of
510 * that function for details. Returns `XYLA_RC_OK' on success,
511 * `XYLA_RC_BAD' if problems are found, or some other code if verification
512 * had to finish prematurely.
517 /*----- That's all, folks -------------------------------------------------*/