Autodoc headers unified to avoid misinterpretation by the build script.
[cake.git] / rom / exec / avl.c
blob0663c5e05727dcb52e0ec39d2e99fc8a8baa28d9
1 /* indent -blC -bli0 -npcs -ncs -i4 -bad -bap avl.c */
2 /*
3 Copyright (c) 2008, The AROS Development Team. All rights reserved.
5 #Description: @AROS.Exec.AVL@
7 <chapter title="Exec AVL Trees">
9 <p>FIXME explain it</p>
11 </chapter>
15 #include <proto/exec.h>
16 #include <exec/avl.h>
18 /* don't think this works inside exec.library */
19 #define D(x)
21 #define LEFT (0)
22 #define RIGHT (1)
24 /* internal functions */
25 /* Re-Links the parent of subroot, properly handling the root-node.
26 The old parent is supplied in parent */
27 static inline int
28 link_parent(struct AVLNode **root, const struct AVLNode *scan,
29 struct AVLNode *subroot, struct AVLNode *parent)
31 int dir;
33 if (parent == NULL)
35 *root = subroot;
36 subroot->avl_parent = NULL;
37 dir = -1;
39 else
41 dir = parent->avl_link[1] == scan;
42 parent->avl_link[dir] = subroot;
43 subroot->avl_parent = parent;
46 return dir;
49 /* Perform a single rotation about next in the given direction.
50 Note that this will be inlined with hard-coded dirs */
51 static inline struct AVLNode *
52 rotate_single(struct AVLNode *scan, struct AVLNode *next, const int dir)
54 struct AVLNode *subroot = next;
55 const int other = dir == 0;
57 D(printf("single %s about %p\n", dir == 0 ? "left" : "right", subroot));
59 scan->avl_link[other] = next->avl_link[dir];
60 if (next->avl_link[dir] != NULL)
61 next->avl_link[dir]->avl_parent = scan;
62 next->avl_link[dir] = scan;
63 scan->avl_parent = next;
65 return subroot;
68 /* Peform a double rotation about scan and then next in a given direction
69 Note that this will be in-lined with hard-coded dirs */
70 static inline struct AVLNode *
71 rotate_double(struct AVLNode *scan, struct AVLNode *next, const int dir)
73 struct AVLNode *subroot = next->avl_link[dir];
74 const int other = dir == 0;
76 D(printf("double %s about %p\n", dir == 0 ? "left" : "right", subroot));
78 next->avl_link[dir] = subroot->avl_link[other];
79 if (subroot->avl_link[other] != NULL)
80 subroot->avl_link[other]->avl_parent = next;
81 subroot->avl_link[other] = next;
82 scan->avl_link[other] = subroot->avl_link[dir];
83 if (subroot->avl_link[dir] != NULL)
84 subroot->avl_link[dir]->avl_parent = scan;
85 subroot->avl_link[dir] = scan;
87 next->avl_parent = subroot;
88 scan->avl_parent = subroot;
90 return subroot;
93 /*****************************************************************************
95 NAME */
97 AROS_LH3I(struct AVLNode *, AVL_AddNode,
99 /* SYNOPSIS */
100 AROS_LHA(struct AVLNode **, root, A0),
101 AROS_LHA(struct AVLNode *, node, A1),
102 AROS_LHA(AVLNODECOMP, func, A2),
103 /* LOCATION */
104 struct ExecBase *, SysBase, 142, Exec)
105 /* FUNCTION
106 Add a new node to an AVL tree.
108 INPUTS
109 Root - The root node of the tree to which the new node will be added.
110 Initially and if the tree is empty, this will be NULL.
112 Node - The new node to add. Any key information must alread be
113 initialised.
115 Func - A key comparison function. It will be passed 2 nodes,
116 node1 and node2 to compare and must return <0, 0 or >0 to
117 reflect node1 < node2, node1 == node, or node1 > node2
118 respectively.
120 RESULT
121 NULL if the node was added to the tree, or a pointer to a node with the
122 same key which already exists in the tree.
124 NOTES
125 AVL trees are balanced binary search trees. This implementation is
126 based on embedding the struct AVLNode within your own data object
127 and providing custom comparison functions wherever they are needed.
129 Two comparison functions are needed for different cases. It is entirely
130 up to the application as to how it interprets the nodes and compares
131 the keys.
133 AVLNODECOMP is used to compare the keys of two nodes.
135 typedef LONG *AVLNODECOMP(const struct AVLNode *avlnode1,
136 const struct AVLNode *avlnode2);
137 D0 A0, A1
139 AVLKEYCOMP is used to compare a key to a node.
141 typedef LONG *AVLKEYCOMP(const struct AVLNode *avlnode,
142 AVLKey key);
143 D0 A0, A1
145 These functions must return the same sense for the same key values.
146 That is,
147 <0 if key of avlnode1 < key of avlnode2
148 if key of avlnode < key
149 0 if key of avlnode1 == key of avlnode2
150 if key of avlnode == key
151 >0 if key of avlnode1 > key of avlnode2
152 if key of avlnode < key
154 Since this function returns the existing node if the keys match,
155 this function can be used to efficiently add items to the tree or
156 update existing items without requiring additional lookups.
158 EXAMPLE
159 This is a fragment which counts the occurances of every word in a file.
160 Also note that this example embeds the struct AVLNode data at
161 the start of the structure, so simple casts suffice for translating
162 AVLNode to ExampleNode addresses.
164 struct ExampleNode {
165 struct AVLNode avl;
166 STRPTR key;
167 ULONG count;
170 static LONG ExampleNodeComp(const struct AVLNode *a1, const struct AVLNode *a2)
172 const struct ExampleNode *e1 = (const struct ExampleNode *)a1;
173 const struct ExampleNode *e2 = (const struct ExampleNode *)e2;
175 return strcmp(a1->key, a2->key);
178 static LONG ExampleKeyComp(const struct AVLNode *a1, AVLKey key)
180 const struct ExampleNode *e1 = (const struct ExampleNode *)a1;
181 char *skey = key;
183 return strcmp(a1->key, skey);
186 void CountWords(wordfile)
188 struct ExampleNode *node;
189 struct AVLNode *root = NULL, *check;
191 node = AllocMem(sizeof(struct ExampleNode), 0);
192 node->count = 1;
194 while (node->key = read_word(wordfile)) {
195 check = AVL_AddNode(&root, &node->avl, ExampleNodecomp);
197 if (check != NULL) {
198 struct ExampleNode *work = (struct ExampleNode *)check;
200 check->count += 1;
201 } else {
202 free(node->key);
203 node = AllocMem(sizeof(struct ExampleNode), 0);
204 node->count = 1;
207 FreeMem(node, sizeof(struct ExampleNode));
210 BUGS
212 SEE ALSO
213 AVL_FindNode(), AVL_FindNextNodeByKey(), AVL_FindPrevNodeByKey(),
214 AVL_RemNodeByAddress(), AVL_RemNodeByKey()
216 INTERNALS
217 ******************************************************************************/
219 AROS_LIBFUNC_INIT;
221 int dir;
222 struct AVLNode *next = *root;
223 struct AVLNode *scan;
224 struct AVLNode *child;
226 /* Simple case - empty tree */
227 if (next == NULL)
229 *root = node;
230 node->avl_link[0] = node->avl_link[1] = node->avl_parent = NULL;
231 node->avl_balance = 0;
232 return NULL;
235 /* find insertion point */
238 LONG cmp;
240 scan = next;
241 cmp = func(scan, node);
242 if (cmp == 0)
243 return (struct AVLNode *)scan;
245 dir = cmp < 0;
246 next = scan->avl_link[dir];
248 while (next != NULL);
250 /* insert */
251 node->avl_parent = scan;
252 scan->avl_link[dir] = node;
253 node->avl_link[0] = node->avl_link[1] = NULL;
254 node->avl_balance = 0;
256 /* update balance factors */
257 while (1)
259 LONG bal = (dir * 2 - 1) + scan->avl_balance;
260 struct AVLNode *parent;
261 struct AVLNode *subroot;
263 switch (bal)
265 case 0:
266 scan->avl_balance = bal;
267 return NULL;
269 case 2:
270 parent = scan->avl_parent;
271 next = scan->avl_link[1];
273 switch (next->avl_balance)
275 case -1:
276 subroot = rotate_double(scan, next, LEFT);
278 if (subroot->avl_balance == 1)
280 scan->avl_balance = -1;
281 next->avl_balance = 0;
283 else if (subroot->avl_balance == -1)
285 scan->avl_balance = 0;
286 next->avl_balance = 1;
288 else
290 scan->avl_balance = next->avl_balance = 0;
293 subroot->avl_balance = 0;
294 break;
295 default:
296 subroot = rotate_single(scan, next, LEFT);
298 scan->avl_balance = next->avl_balance = 0;
299 break;
302 link_parent(root, scan, subroot, parent);
303 return NULL;
305 case -2:
306 parent = scan->avl_parent;
307 next = scan->avl_link[0];
309 switch (next->avl_balance)
311 case 1:
312 subroot = rotate_double(scan, next, RIGHT);
314 if (subroot->avl_balance == -1)
316 scan->avl_balance = 1;
317 next->avl_balance = 0;
319 else if (subroot->avl_balance == 1)
321 scan->avl_balance = 0;
322 next->avl_balance = -1;
324 else
326 scan->avl_balance = next->avl_balance = 0;
329 subroot->avl_balance = 0;
330 break;
331 default:
332 subroot = rotate_single(scan, next, RIGHT);
334 scan->avl_balance = next->avl_balance = 0;
335 break;
338 link_parent(root, scan, subroot, parent);
339 return NULL;
341 default:
342 scan->avl_balance = bal;
344 child = scan;
345 scan = scan->avl_parent;
346 if (scan == NULL)
347 return NULL;
349 dir = scan->avl_link[1] == child;
350 break;
354 return NULL;
356 AROS_LIBFUNC_EXIT;
357 } /* AVL_AddNode */
359 /*****************************************************************************
361 NAME */
363 AROS_LH2I(struct AVLNode *, AVL_RemNodeByAddress,
365 /* SYNOPSIS */
366 AROS_LHA(struct AVLNode **, Root, A0),
367 AROS_LHA(struct AVLNode *, Node, A1),
368 /* LOCATION */
369 struct ExecBase *, SysBase, 143, Exec)
370 /* FUNCTION
371 Remove a given node from the tree.
373 INPUTS
374 Root - A pointer to a pointer to the root node of the tree.
376 Node - A struct AVLNode to remove. The node must be present
377 in the tree.
379 RESULT
380 Node is returned.
382 NOTES
383 Removing a node may require multiple rebalancing steps
384 in the tree. Each step however runs in constant time
385 and no more than 1.44log(n) steps will be required.
387 EXAMPLE
388 See AVL_NextNodeByAddress(), AVL_PrevNodeByAddress()
390 BUGS
392 SEE ALSO
393 AVL_AddNode(), AVL_FindNode(), AVL_NextNodeByAddress(),
394 AVL_PrevNodeByAddress()
396 INTERNALS
397 ******************************************************************************/
399 AROS_LIBFUNC_INIT;
401 struct AVLNode *scan;
402 struct AVLNode *node = (struct AVLNode *)Node;
403 struct AVLNode **root = (struct AVLNode **)Root;
404 int dir;
406 if (node->avl_link[0] == NULL)
408 if (node->avl_link[1] == NULL)
410 if (node->avl_parent == NULL)
412 /* removed last node */
413 *root = NULL;
414 return Node;
416 else
418 /* removed a leaf */
419 scan = node->avl_parent;
420 dir = scan->avl_link[1] == node;
421 scan->avl_link[dir] = NULL;
422 D(printf("removed leaf dir = %d\n", dir));
425 else
427 if (node->avl_parent == NULL)
429 /* removed root left-leaf node */
430 *root = node->avl_link[1];
431 node->avl_link[1]->avl_parent = NULL;
432 return Node;
434 else
436 /* removed a left-leaf */
437 scan = node->avl_parent;
438 dir = scan->avl_link[1] == node;
439 scan->avl_link[dir] = node->avl_link[1];
440 node->avl_link[1]->avl_parent = scan;
441 D(printf("removed left leaf dir =%d\n", dir));
445 else
447 if (node->avl_link[1] == NULL)
449 if (node->avl_parent == NULL)
451 /* removed root right-leaf node */
452 *root = node->avl_link[0];
453 node->avl_link[0]->avl_parent = NULL;
454 return Node;
456 else
458 /* removed a right-leaf */
459 scan = node->avl_parent;
460 dir = scan->avl_link[1] == node;
461 scan->avl_link[dir] = node->avl_link[0];
462 node->avl_link[0]->avl_parent = scan;
463 D(printf("removed right leaf dir=%d\n", dir));
466 else
468 /* removing a non-leaf node - swap it with a leaf node and 'remove' that instead */
469 struct AVLNode *toremove = (struct AVLNode *)AVL_FindPrevNodeByAddress(Node); // do we do prev/next based on balance factor? */
471 D(printf("removing non-leaf key ... %p\n", toremove));
473 /* remove the leaf node */
474 scan = toremove->avl_parent;
476 if (scan == node)
478 /* special case - immediate child of what we're removing */
479 toremove->avl_link[1] = node->avl_link[1];
480 if (node->avl_link[1] != NULL)
481 node->avl_link[1]->avl_parent = toremove;
482 dir = 0;
483 scan = toremove;
484 D(printf(" removed immediate child\n"));
486 else
488 dir = toremove->avl_parent->avl_link[1] == toremove;
489 toremove->avl_parent->avl_link[dir] = toremove->avl_link[0];
490 if (toremove->avl_link[0] != NULL)
491 toremove->avl_link[0]->avl_parent = toremove->avl_parent;
493 /* swap it with the removed node */
494 toremove->avl_link[0] = node->avl_link[0];
495 if (node->avl_link[0] != NULL)
496 node->avl_link[0]->avl_parent = toremove;
497 toremove->avl_link[1] = node->avl_link[1];
498 if (node->avl_link[1] != NULL)
499 node->avl_link[1]->avl_parent = toremove;
500 D(printf(" removed distant child\n"));
502 toremove->avl_balance = node->avl_balance;
503 toremove->avl_parent = node->avl_parent;
504 if (node->avl_parent == NULL)
505 *root = toremove;
506 else
507 node->avl_parent->avl_link[node->avl_parent->avl_link[1] ==
508 node] = toremove;
510 D(printf("removed key, tree is now:\n"));
511 D(dumptree(*root, 0));
515 /* rebalance from 'scan' up */
516 while (1)
518 int bal = scan->avl_balance - (dir * 2 - 1);
519 struct AVLNode *next;
520 struct AVLNode *parent;
521 struct AVLNode *subroot;
523 switch (bal)
525 case 0:
526 scan->avl_balance = bal;
528 parent = scan->avl_parent;
529 if (parent == NULL)
530 return Node;
532 dir = parent->avl_link[1] == scan;
533 scan = parent;
534 break;
536 case -1:
537 case 1:
538 scan->avl_balance = bal;
539 return Node;
541 case 2:
542 parent = scan->avl_parent;
543 next = scan->avl_link[1];
545 switch (next->avl_balance)
547 case 0:
548 subroot = rotate_single(scan, next, LEFT);
549 scan->avl_balance = 1;
550 next->avl_balance = -1;
551 // stop
552 link_parent(root, scan, subroot, parent);
553 return Node;
554 case 1:
555 subroot = rotate_single(scan, next, LEFT);
556 scan->avl_balance = 0;
557 next->avl_balance = 0;
558 // keep going
559 break;
560 case -1:
561 subroot = rotate_double(scan, next, LEFT);
563 if (subroot->avl_balance == 1)
565 scan->avl_balance = -1;
566 next->avl_balance = 0;
568 else if (subroot->avl_balance == -1)
570 scan->avl_balance = 0;
571 next->avl_balance = 1;
573 else
575 scan->avl_balance = 0;
576 next->avl_balance = 0;
579 subroot->avl_balance = 0;
580 // keep going
581 break;
584 dir = link_parent(root, scan, subroot, parent);
585 if (dir == -1)
586 return Node;
588 scan = parent;
589 break;
591 case -2:
592 parent = scan->avl_parent;
593 next = scan->avl_link[0];
595 switch (next->avl_balance)
597 case 0:
598 subroot = rotate_single(scan, next, RIGHT);
599 scan->avl_balance = -1;
600 next->avl_balance = 1;
601 // stop
602 link_parent(root, scan, subroot, parent);
603 return Node;
604 case -1:
605 subroot = rotate_single(scan, next, RIGHT);
606 scan->avl_balance = next->avl_balance = 0;
607 // keep going
608 break;
609 case +1:
610 subroot = rotate_double(scan, next, RIGHT);
612 if (subroot->avl_balance == -1)
614 scan->avl_balance = 1;
615 next->avl_balance = 0;
617 else if (subroot->avl_balance == 1)
619 scan->avl_balance = 0;
620 next->avl_balance = -1;
622 else
624 scan->avl_balance = 0;
625 next->avl_balance = 0;
628 subroot->avl_balance = 0;
629 // keep going
630 break;
633 dir = link_parent(root, scan, subroot, parent);
634 if (dir == -1)
635 return Node;
637 scan = parent;
638 break;
642 AROS_LIBFUNC_EXIT;
643 } /* AVL_RemNodeByAddress */
645 /*****************************************************************************
647 NAME */
649 AROS_LH3I(struct AVLNode *, AVL_RemNodeByKey,
651 /* SYNOPSIS */
652 AROS_LHA(struct AVLNode **, root, A0),
653 AROS_LHA(AVLKey, key, A1), AROS_LHA(AVLKEYCOMP, func, A2),
654 /* LOCATION */
655 struct ExecBase *, SysBase, 144, Exec)
656 /* FUNCTION
657 Looks up a node in the tree by key, and removes it if it
658 is found.
660 INPUTS
661 Root - A pointer to a pointer to the root node of the AVL tree.
663 key - The key to search for.
665 func - An AVLKEYCOMP function used to compare the key and nodes
666 in the tree.
668 RESULT
669 If the key was present in the tree, then a pointer to the node
670 for that key. Otherwise NULL if no such key existed in the
671 tree.
673 NOTES
674 See AVL_RemNodeByAddress().
676 EXAMPLE
678 BUGS
680 SEE ALSO
681 AVL_AddNode(), AVL_RemNodeByAddress()
683 INTERNALS
684 ******************************************************************************/
686 AROS_LIBFUNC_INIT;
688 struct AVLNode *node;
690 node = AVL_FindNode(*root, key, func);
692 if (node != NULL)
693 node = AVL_RemNodeByAddress(root, node);
695 return node;
697 AROS_LIBFUNC_EXIT;
698 } /* AVL_RemNodeByKey */
700 /*****************************************************************************
702 NAME */
704 AROS_LH3I(struct AVLNode *, AVL_FindNode,
706 /* SYNOPSIS */
707 AROS_LHA(const struct AVLNode *, Root, A0),
708 AROS_LHA(AVLKey, key, A1), AROS_LHA(AVLKEYCOMP, func, A2),
709 /* LOCATION */
710 struct ExecBase *, SysBase, 145, Exec)
711 /* FUNCTION
712 Find an entry in the AVL tree by key.
714 INPUTS
715 Root - The root of the AVL tree.
717 key - The key to search.
719 func - The AVLKEYCOMP key comparision function for this tree.
721 RESULT
722 A pointer to the node matching key if it exists in the
723 tree, or NULL if no such node exists.
725 NOTES
727 EXAMPLE
728 node = (struct ExampleNode *)AVL_FindNode(root, "aros", ExampleKeyComp);
729 if (node)
730 printf(" `%s' occurs %d times\n", node->key, node->count);
732 BUGS
734 SEE ALSO
735 AVL_AddNode(), AVL_RemNodeByAddress(), AVL_FindNextNodeByAddress(),
736 AVL_FindPrevNodeByAddress()
738 INTERNALS
739 ******************************************************************************/
741 AROS_LIBFUNC_INIT;
743 struct AVLNode *node = (struct AVLNode *)Root;
744 LONG cmp;
746 while (node != NULL && (cmp = func((struct AVLNode *)node, key)) != 0)
748 node = node->avl_link[cmp < 0];
751 return (struct AVLNode *)node;
753 AROS_LIBFUNC_EXIT;
754 } /* AVL_FindNode */
756 /*****************************************************************************
758 NAME */
760 AROS_LH1I(struct AVLNode *, AVL_FindPrevNodeByAddress,
762 /* SYNOPSIS */
763 AROS_LHA(const struct AVLNode *, Node, A0),
764 /* LOCATION */
765 struct ExecBase *, SysBase, 146, Exec)
766 /* FUNCTION
767 Perform an inverse-order traversal to the previous node in the tree.
769 INPUTS
770 Node - The current node. The node must be present in the tree.
772 RESULT
773 The next-least node in the tree, or NULL if Node was already
774 the lowest valued node in the tree.
776 NOTES
777 This implementation uses a parent pointer to avoid needing
778 a stack or state to track it's current position in the tree.
780 Although this operation is typically O(1), in the worst case it
781 iterate the full depth of the tree - approximately 1.44Log(N).
783 EXAMPLE
784 ... inverse-order traversal of all nodes
785 node = (struct ExampleNode *)AVL_FindLastNode(root);
786 while (node) {
787 printf(" %s\n", node->key);
788 node = (struct ExampleNode *)AVL_FindPrevNodeByAddress(node);
791 ... inverse-order traversal of all nodes - with safe deletion
792 node = (struct ExampleNode *)AVL_FindLastNode(root);
793 prev = (struct ExampleNode *)AVL_FindPrevNodeByAddress(node);
794 while (node) {
795 printf(" %s\n", node->key);
797 if (DELETE_NODE(node))
798 AVL_RemNodeByAddress(&root, node);
800 node = prev;
801 prev = (struct ExampleNode *)AVL_FindPrevNodeByAddress(node);
804 BUGS
806 SEE ALSO
807 AVL_AddNode(), AVL_RemNodeByAddress(), AVL_FindLastNode()
809 INTERNALS
810 ******************************************************************************/
812 AROS_LIBFUNC_INIT;
814 const struct AVLNode *node = (const struct AVLNode *)Node;
815 const struct AVLNode *prev;
817 prev = node->avl_link[0];
818 if (prev != NULL)
822 node = prev;
823 prev = prev->avl_link[1];
825 while (prev);
827 else
831 prev = node;
832 node = node->avl_parent;
834 while (node != NULL && node->avl_link[1] != prev);
837 return (struct AVLNode *)node;
839 AROS_LIBFUNC_EXIT;
840 } /* AVL_FindPrevNodeByAddress */
842 /*****************************************************************************
844 NAME */
846 AROS_LH3I(struct AVLNode *, AVL_FindPrevNodeByKey,
848 /* SYNOPSIS */
849 AROS_LHA(const struct AVLNode *, root, A0),
850 AROS_LHA(AVLKey, key, A1), AROS_LHA(AVLKEYCOMP, func, A2),
851 /* LOCATION */
852 struct ExecBase *, SysBase, 147, Exec)
853 /* FUNCTION
854 Find the node matching the key, or if such a node does not exist,
855 then the node with the next-lowest value.
857 INPUTS
858 Root - The root of the AVL tree.
860 key - The key to search.
862 func - The AVLKEYCOMP key comparision function for this tree.
864 RESULT
865 A pointer to the struct AVLNode which matches this key, or
866 if that key is not present in the tree, the next lowest node.
867 Or NULL if key is lower than the key of any node in the tree.
869 NOTES
870 This is only O(1.44log(n)) in the worst case.
872 EXAMPLE
874 BUGS
876 SEE ALSO
877 AVL_AddNode(), AVL_FindNextNodeByAddress(), AVL_FindLastNode()
879 INTERNALS
880 ******************************************************************************/
882 AROS_LIBFUNC_INIT;
884 struct AVLNode *node = (struct AVLNode *)root;
885 struct AVLNode *lesser = NULL;
886 LONG cmp;
888 while (node != NULL && (cmp = func((struct AVLNode *)node, key)) != 0)
890 if (cmp < 0)
891 lesser = node;
892 node = node->avl_link[cmp < 0];
895 return (struct AVLNode *)(node != NULL ? node : lesser);
897 AROS_LIBFUNC_EXIT;
898 } /* AVL_FindPrevNodeByKey */
900 /*****************************************************************************
902 NAME */
904 AROS_LH1I(struct AVLNode *, AVL_FindNextNodeByAddress,
906 /* SYNOPSIS */
907 AROS_LHA(const struct AVLNode *, Node, A0),
908 /* LOCATION */
909 struct ExecBase *, SysBase, 148, Exec)
910 /* FUNCTION
911 Perform an in-order traversal to the next node in the tree.
913 INPUTS
914 Node - The current node. The node must be present in the tree.
916 RESULT
917 The next-greatest node in the tree, or NULL if Node was already
918 the highest valued node in the tree.
920 NOTES
921 This implementation uses a parent pointer to avoid needing
922 a stack or state to track it's current position in the tree.
924 Although this operation is typically O(1), in the worst case it
925 iterate the full depth of the tree - approximately 1.44Log(N).
927 EXAMPLE
928 ... in-order traversal of all nodes
929 node = (struct ExampleNode *)AVL_FindFirstNode(root);
930 while (node) {
931 printf(" %s\n", node->key);
932 node = (struct ExampleNode *)AVL_FindNextNodeByAddress(node);
935 ... in-order traversal of all nodes - with safe deletion
936 node = (struct ExampleNode *)AVL_FindFirstNode(root);
937 next = (struct ExampleNode *)AVL_FindNextNodeByAddress(node);
938 while (node) {
939 printf(" %s\n", node->key);
941 if (DELETE_NODE(node))
942 AVL_RemNodeByAddress(&root, node);
944 node = next;
945 next = (struct ExampleNode *)AVL_FindNextNodeByAddress(node);
948 BUGS
950 SEE ALSO
951 AVL_AddNode(), AVL_RemNodeByAddress(), AVL_FindFirstNode()
953 INTERNALS
954 ******************************************************************************/
956 AROS_LIBFUNC_INIT;
958 const struct AVLNode *node = (const struct AVLNode *)Node;
959 const struct AVLNode *next;
961 next = node->avl_link[1];
962 if (next != NULL)
966 node = next;
967 next = node->avl_link[0];
969 while (next != NULL);
971 else
975 next = node;
976 node = node->avl_parent;
978 while (node != NULL && node->avl_link[1] == next);
981 return (struct AVLNode *)node;
983 AROS_LIBFUNC_EXIT;
984 } /* AVL_FindNextNodeByAddress */
986 /*****************************************************************************
988 NAME */
990 AROS_LH3I(struct AVLNode *, AVL_FindNextNodeByKey,
992 /* SYNOPSIS */
993 AROS_LHA(const struct AVLNode *, Root, A0),
994 AROS_LHA(AVLKey, key, A1), AROS_LHA(AVLKEYCOMP, func, A2),
995 /* LOCATION */
996 struct ExecBase *, SysBase, 149, Exec)
997 /* FUNCTION
998 Find the node matching the key, or if such a node does not exist,
999 then the node with the next-highest value.
1001 INPUTS
1002 Root - The root of the AVL tree.
1004 key - The key to search.
1006 func - The AVLKEYCOMP key comparision function for this tree.
1008 RESULT
1009 A pointer to the struct AVLNode which matches this key, or
1010 if that key is not present in the tree, the next highest node.
1011 Or NULL if key is higher than the key of any node in the tree.
1013 NOTES
1014 This is only O(1.44log(n)) in the worst case.
1016 EXAMPLE
1018 BUGS
1020 SEE ALSO
1021 AVL_AddNode(), AVL_FindNextNodeByAddress(), AVL_FindLastNode()
1023 INTERNALS
1024 ******************************************************************************/
1026 AROS_LIBFUNC_INIT;
1028 struct AVLNode *node = (struct AVLNode *)Root;
1029 struct AVLNode *greater = NULL;
1030 LONG cmp;
1032 while (node != NULL && (cmp = func((struct AVLNode *)node, key)) != 0)
1034 if (cmp > 0)
1035 greater = node;
1036 node = node->avl_link[cmp < 0];
1039 return (struct AVLNode *)(node != NULL ? node : greater);
1041 AROS_LIBFUNC_EXIT;
1042 } /* AVL_FindNextNodeByKey */
1044 /*****************************************************************************
1046 NAME */
1048 AROS_LH1I(struct AVLNode *, AVL_FindFirstNode,
1050 /* SYNOPSIS */
1051 AROS_LHA(const struct AVLNode *, Root, A0),
1052 /* LOCATION */
1053 struct ExecBase *, SysBase, 150, Exec)
1054 /* FUNCTION
1055 Find the smallest node in an AVL tree.
1057 INPUTS
1058 Root - The root node of the AVL tree.
1060 RESULT
1061 NULL if the tree is empty (i.e. Root is NULL), or the node
1062 which contains the least value in the tree as determined by
1063 the comparision function used to add the node.
1065 NOTES
1066 AVL trees are balanced but not minimal. This operation
1067 must iterate the full depth of the tree on one side -
1068 approximately 1.44Log(N).
1070 EXAMPLE
1071 See AVL_FindNextNodeByAddress()
1073 BUGS
1075 SEE ALSO
1076 AVL_AddNode(), AVL_FindNextNodeByAddress()
1078 INTERNALS
1079 ******************************************************************************/
1081 AROS_LIBFUNC_INIT;
1083 struct AVLNode *node = (struct AVLNode *)Root;
1085 if (node != NULL)
1086 while (node->avl_link[0] != NULL)
1087 node = node->avl_link[0];
1089 return (struct AVLNode *)node;
1091 AROS_LIBFUNC_EXIT;
1092 } /* AVL_FindFirstNode */
1094 /*****************************************************************************
1096 NAME */
1098 AROS_LH1I(struct AVLNode *, AVL_FindLastNode,
1100 /* SYNOPSIS */
1101 AROS_LHA(const struct AVLNode *, Root, A0),
1102 /* LOCATION */
1103 struct ExecBase *, SysBase, 151, Exec)
1104 /* FUNCTION
1105 Find the largest node in an AVL tree.
1107 INPUTS
1108 Root - The root node of the AVL tree.
1110 RESULT
1111 NULL if the tree is empty (i.e. Root is NULL), or the node
1112 which contains the greatest value in the tree as determined by
1113 the comparision function used to add the node.
1115 NOTES
1116 AVL trees are balanced but not minimal. This operation
1117 must iterate the full depth of the tree on one side -
1118 approximately 1.44Log(N).
1120 EXAMPLE
1121 See AVL_FindPrevNodeByAddress()
1123 BUGS
1125 SEE ALSO
1126 AVL_AddNode(), AVL_FindPrevNodeByAddress()
1128 INTERNALS
1129 ******************************************************************************/
1131 AROS_LIBFUNC_INIT;
1133 struct AVLNode *node = (struct AVLNode *)Root;
1135 if (node != NULL)
1136 while (node->avl_link[1] != NULL)
1137 node = node->avl_link[1];
1139 return (struct AVLNode *)node;
1141 AROS_LIBFUNC_EXIT;
1142 } /* AVL_FindLastNode */