1 /* indent -blC -bli0 -npcs -ncs -i4 -bad -bap avl.c */
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>
15 #include <proto/exec.h>
18 /* don't think this works inside exec.library */
24 /* internal functions */
25 /* Re-Links the parent of subroot, properly handling the root-node.
26 The old parent is supplied in parent */
28 link_parent(struct AVLNode
**root
, const struct AVLNode
*scan
,
29 struct AVLNode
*subroot
, struct AVLNode
*parent
)
36 subroot
->avl_parent
= NULL
;
41 dir
= parent
->avl_link
[1] == scan
;
42 parent
->avl_link
[dir
] = subroot
;
43 subroot
->avl_parent
= parent
;
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
;
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
;
93 /*****************************************************************************
97 AROS_LH3I(struct AVLNode
*, AVL_AddNode
,
100 AROS_LHA(struct AVLNode
**, root
, A0
),
101 AROS_LHA(struct AVLNode
*, node
, A1
),
102 AROS_LHA(AVLNODECOMP
, func
, A2
),
104 struct ExecBase
*, SysBase
, 142, Exec
)
106 Add a new node to an AVL tree.
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
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
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.
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
133 AVLNODECOMP is used to compare the keys of two nodes.
135 typedef LONG *AVLNODECOMP(const struct AVLNode *avlnode1,
136 const struct AVLNode *avlnode2);
139 AVLKEYCOMP is used to compare a key to a node.
141 typedef LONG *AVLKEYCOMP(const struct AVLNode *avlnode,
145 These functions must return the same sense for the same key values.
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.
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.
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;
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);
194 while (node->key = read_word(wordfile)) {
195 check = AVL_AddNode(&root, &node->avl, ExampleNodecomp);
198 struct ExampleNode *work = (struct ExampleNode *)check;
203 node = AllocMem(sizeof(struct ExampleNode), 0);
207 FreeMem(node, sizeof(struct ExampleNode));
213 AVL_FindNode(), AVL_FindNextNodeByKey(), AVL_FindPrevNodeByKey(),
214 AVL_RemNodeByAddress(), AVL_RemNodeByKey()
217 ******************************************************************************/
222 struct AVLNode
*next
= *root
;
223 struct AVLNode
*scan
;
224 struct AVLNode
*child
;
226 /* Simple case - empty tree */
230 node
->avl_link
[0] = node
->avl_link
[1] = node
->avl_parent
= NULL
;
231 node
->avl_balance
= 0;
235 /* find insertion point */
241 cmp
= AROS_UFC2(LONG
, func
,
242 AROS_UFCA(const struct AVLNode
*, scan
, A0
),
243 AROS_UFCA(const struct AVLNode
*, node
, A1
));
245 return (struct AVLNode
*)scan
;
248 next
= scan
->avl_link
[dir
];
250 while (next
!= NULL
);
253 node
->avl_parent
= scan
;
254 scan
->avl_link
[dir
] = node
;
255 node
->avl_link
[0] = node
->avl_link
[1] = NULL
;
256 node
->avl_balance
= 0;
258 /* update balance factors */
261 LONG bal
= (dir
* 2 - 1) + scan
->avl_balance
;
262 struct AVLNode
*parent
;
263 struct AVLNode
*subroot
;
268 scan
->avl_balance
= bal
;
272 parent
= scan
->avl_parent
;
273 next
= scan
->avl_link
[1];
275 switch (next
->avl_balance
)
278 subroot
= rotate_double(scan
, next
, LEFT
);
280 if (subroot
->avl_balance
== 1)
282 scan
->avl_balance
= -1;
283 next
->avl_balance
= 0;
285 else if (subroot
->avl_balance
== -1)
287 scan
->avl_balance
= 0;
288 next
->avl_balance
= 1;
292 scan
->avl_balance
= next
->avl_balance
= 0;
295 subroot
->avl_balance
= 0;
298 subroot
= rotate_single(scan
, next
, LEFT
);
300 scan
->avl_balance
= next
->avl_balance
= 0;
304 link_parent(root
, scan
, subroot
, parent
);
308 parent
= scan
->avl_parent
;
309 next
= scan
->avl_link
[0];
311 switch (next
->avl_balance
)
314 subroot
= rotate_double(scan
, next
, RIGHT
);
316 if (subroot
->avl_balance
== -1)
318 scan
->avl_balance
= 1;
319 next
->avl_balance
= 0;
321 else if (subroot
->avl_balance
== 1)
323 scan
->avl_balance
= 0;
324 next
->avl_balance
= -1;
328 scan
->avl_balance
= next
->avl_balance
= 0;
331 subroot
->avl_balance
= 0;
334 subroot
= rotate_single(scan
, next
, RIGHT
);
336 scan
->avl_balance
= next
->avl_balance
= 0;
340 link_parent(root
, scan
, subroot
, parent
);
344 scan
->avl_balance
= bal
;
347 scan
= scan
->avl_parent
;
351 dir
= scan
->avl_link
[1] == child
;
361 /*****************************************************************************
365 AROS_LH2I(struct AVLNode
*, AVL_RemNodeByAddress
,
368 AROS_LHA(struct AVLNode
**, Root
, A0
),
369 AROS_LHA(struct AVLNode
*, Node
, A1
),
371 struct ExecBase
*, SysBase
, 143, Exec
)
373 Remove a given node from the tree.
376 Root - A pointer to a pointer to the root node of the tree.
378 Node - A struct AVLNode to remove. The node must be present
385 Removing a node may require multiple rebalancing steps
386 in the tree. Each step however runs in constant time
387 and no more than 1.44log(n) steps will be required.
390 See AVL_FindNextNodeByAddress(), AVL_FindPrevNodeByAddress()
395 AVL_AddNode(), AVL_FindNode(), AVL_FindNextNodeByAddress(),
396 AVL_FindPrevNodeByAddress()
399 ******************************************************************************/
403 struct AVLNode
*scan
;
404 struct AVLNode
*node
= (struct AVLNode
*)Node
;
405 struct AVLNode
**root
= (struct AVLNode
**)Root
;
408 if (node
->avl_link
[0] == NULL
)
410 if (node
->avl_link
[1] == NULL
)
412 if (node
->avl_parent
== NULL
)
414 /* removed last node */
421 scan
= node
->avl_parent
;
422 dir
= scan
->avl_link
[1] == node
;
423 scan
->avl_link
[dir
] = NULL
;
424 D(printf("removed leaf dir = %d\n", dir
));
429 if (node
->avl_parent
== NULL
)
431 /* removed root left-leaf node */
432 *root
= node
->avl_link
[1];
433 node
->avl_link
[1]->avl_parent
= NULL
;
438 /* removed a left-leaf */
439 scan
= node
->avl_parent
;
440 dir
= scan
->avl_link
[1] == node
;
441 scan
->avl_link
[dir
] = node
->avl_link
[1];
442 node
->avl_link
[1]->avl_parent
= scan
;
443 D(printf("removed left leaf dir =%d\n", dir
));
449 if (node
->avl_link
[1] == NULL
)
451 if (node
->avl_parent
== NULL
)
453 /* removed root right-leaf node */
454 *root
= node
->avl_link
[0];
455 node
->avl_link
[0]->avl_parent
= NULL
;
460 /* removed a right-leaf */
461 scan
= node
->avl_parent
;
462 dir
= scan
->avl_link
[1] == node
;
463 scan
->avl_link
[dir
] = node
->avl_link
[0];
464 node
->avl_link
[0]->avl_parent
= scan
;
465 D(printf("removed right leaf dir=%d\n", dir
));
470 /* removing a non-leaf node - swap it with a leaf node and 'remove' that instead */
471 struct AVLNode
*toremove
= (struct AVLNode
*)AVL_FindPrevNodeByAddress(Node
); // do we do prev/next based on balance factor? */
473 D(printf("removing non-leaf key ... %p\n", toremove
));
475 /* remove the leaf node */
476 scan
= toremove
->avl_parent
;
480 /* special case - immediate child of what we're removing */
481 toremove
->avl_link
[1] = node
->avl_link
[1];
482 if (node
->avl_link
[1] != NULL
)
483 node
->avl_link
[1]->avl_parent
= toremove
;
486 D(printf(" removed immediate child\n"));
490 dir
= toremove
->avl_parent
->avl_link
[1] == toremove
;
491 toremove
->avl_parent
->avl_link
[dir
] = toremove
->avl_link
[0];
492 if (toremove
->avl_link
[0] != NULL
)
493 toremove
->avl_link
[0]->avl_parent
= toremove
->avl_parent
;
495 /* swap it with the removed node */
496 toremove
->avl_link
[0] = node
->avl_link
[0];
497 if (node
->avl_link
[0] != NULL
)
498 node
->avl_link
[0]->avl_parent
= toremove
;
499 toremove
->avl_link
[1] = node
->avl_link
[1];
500 if (node
->avl_link
[1] != NULL
)
501 node
->avl_link
[1]->avl_parent
= toremove
;
502 D(printf(" removed distant child\n"));
504 toremove
->avl_balance
= node
->avl_balance
;
505 toremove
->avl_parent
= node
->avl_parent
;
506 if (node
->avl_parent
== NULL
)
509 node
->avl_parent
->avl_link
[node
->avl_parent
->avl_link
[1] ==
512 D(printf("removed key, tree is now:\n"));
513 D(dumptree(*root
, 0));
517 /* rebalance from 'scan' up */
520 int bal
= scan
->avl_balance
- (dir
* 2 - 1);
521 struct AVLNode
*next
;
522 struct AVLNode
*parent
;
523 struct AVLNode
*subroot
= NULL
;
528 scan
->avl_balance
= bal
;
530 parent
= scan
->avl_parent
;
534 dir
= parent
->avl_link
[1] == scan
;
540 scan
->avl_balance
= bal
;
544 parent
= scan
->avl_parent
;
545 next
= scan
->avl_link
[1];
547 switch (next
->avl_balance
)
550 subroot
= rotate_single(scan
, next
, LEFT
);
551 scan
->avl_balance
= 1;
552 next
->avl_balance
= -1;
554 link_parent(root
, scan
, subroot
, parent
);
557 subroot
= rotate_single(scan
, next
, LEFT
);
558 scan
->avl_balance
= 0;
559 next
->avl_balance
= 0;
563 subroot
= rotate_double(scan
, next
, LEFT
);
565 if (subroot
->avl_balance
== 1)
567 scan
->avl_balance
= -1;
568 next
->avl_balance
= 0;
570 else if (subroot
->avl_balance
== -1)
572 scan
->avl_balance
= 0;
573 next
->avl_balance
= 1;
577 scan
->avl_balance
= 0;
578 next
->avl_balance
= 0;
581 subroot
->avl_balance
= 0;
586 dir
= link_parent(root
, scan
, subroot
, parent
);
594 parent
= scan
->avl_parent
;
595 next
= scan
->avl_link
[0];
597 switch (next
->avl_balance
)
600 subroot
= rotate_single(scan
, next
, RIGHT
);
601 scan
->avl_balance
= -1;
602 next
->avl_balance
= 1;
604 link_parent(root
, scan
, subroot
, parent
);
607 subroot
= rotate_single(scan
, next
, RIGHT
);
608 scan
->avl_balance
= next
->avl_balance
= 0;
612 subroot
= rotate_double(scan
, next
, RIGHT
);
614 if (subroot
->avl_balance
== -1)
616 scan
->avl_balance
= 1;
617 next
->avl_balance
= 0;
619 else if (subroot
->avl_balance
== 1)
621 scan
->avl_balance
= 0;
622 next
->avl_balance
= -1;
626 scan
->avl_balance
= 0;
627 next
->avl_balance
= 0;
630 subroot
->avl_balance
= 0;
635 dir
= link_parent(root
, scan
, subroot
, parent
);
645 } /* AVL_RemNodeByAddress */
647 /*****************************************************************************
651 AROS_LH3I(struct AVLNode
*, AVL_RemNodeByKey
,
654 AROS_LHA(struct AVLNode
**, root
, A0
),
655 AROS_LHA(AVLKey
, key
, A1
), AROS_LHA(AVLKEYCOMP
, func
, A2
),
657 struct ExecBase
*, SysBase
, 144, Exec
)
659 Looks up a node in the tree by key, and removes it if it
663 Root - A pointer to a pointer to the root node of the AVL tree.
665 key - The key to search for.
667 func - An AVLKEYCOMP function used to compare the key and nodes
671 If the key was present in the tree, then a pointer to the node
672 for that key. Otherwise NULL if no such key existed in the
676 See AVL_RemNodeByAddress().
683 AVL_AddNode(), AVL_RemNodeByAddress()
686 ******************************************************************************/
690 struct AVLNode
*node
;
692 node
= AVL_FindNode(*root
, key
, func
);
695 node
= AVL_RemNodeByAddress(root
, node
);
700 } /* AVL_RemNodeByKey */
702 /*****************************************************************************
706 AROS_LH3I(struct AVLNode
*, AVL_FindNode
,
709 AROS_LHA(const struct AVLNode
*, Root
, A0
),
710 AROS_LHA(AVLKey
, key
, A1
), AROS_LHA(AVLKEYCOMP
, func
, A2
),
712 struct ExecBase
*, SysBase
, 145, Exec
)
714 Find an entry in the AVL tree by key.
717 Root - The root of the AVL tree.
719 key - The key to search.
721 func - The AVLKEYCOMP key comparision function for this tree.
724 A pointer to the node matching key if it exists in the
725 tree, or NULL if no such node exists.
730 node = (struct ExampleNode *)AVL_FindNode(root, "aros", ExampleKeyComp);
732 printf(" `%s' occurs %d times\n", node->key, node->count);
737 AVL_AddNode(), AVL_RemNodeByAddress(), AVL_FindNextNodeByAddress(),
738 AVL_FindPrevNodeByAddress()
741 ******************************************************************************/
745 struct AVLNode
*node
= (struct AVLNode
*)Root
;
748 while (node
!= NULL
&&
749 (cmp
= AROS_UFC2(LONG
, func
,
750 AROS_UFCA(const struct AVLNode
*, node
, A0
),
751 AROS_UFCA(AVLKey
, key
, A1
))) != 0)
753 node
= node
->avl_link
[cmp
< 0];
756 return (struct AVLNode
*)node
;
761 /*****************************************************************************
765 AROS_LH1I(struct AVLNode
*, AVL_FindPrevNodeByAddress
,
768 AROS_LHA(const struct AVLNode
*, Node
, A0
),
770 struct ExecBase
*, SysBase
, 146, Exec
)
772 Perform an inverse-order traversal to the previous node in the tree.
775 Node - The current node. The node must be present in the tree.
778 The next-least node in the tree, or NULL if Node was already
779 the lowest valued node in the tree.
782 This implementation uses a parent pointer to avoid needing
783 a stack or state to track it's current position in the tree.
785 Although this operation is typically O(1), in the worst case it
786 iterate the full depth of the tree - approximately 1.44Log(N).
789 ... inverse-order traversal of all nodes
790 node = (struct ExampleNode *)AVL_FindLastNode(root);
792 printf(" %s\n", node->key);
793 node = (struct ExampleNode *)AVL_FindPrevNodeByAddress(node);
796 ... inverse-order traversal of all nodes - with safe deletion
797 node = (struct ExampleNode *)AVL_FindLastNode(root);
798 prev = (struct ExampleNode *)AVL_FindPrevNodeByAddress(node);
800 printf(" %s\n", node->key);
802 if (DELETE_NODE(node))
803 AVL_RemNodeByAddress(&root, node);
806 prev = (struct ExampleNode *)AVL_FindPrevNodeByAddress(node);
812 AVL_AddNode(), AVL_RemNodeByAddress(), AVL_FindLastNode()
815 ******************************************************************************/
819 const struct AVLNode
*node
= (const struct AVLNode
*)Node
;
820 const struct AVLNode
*prev
;
822 prev
= node
->avl_link
[0];
828 prev
= prev
->avl_link
[1];
837 node
= node
->avl_parent
;
839 while (node
!= NULL
&& node
->avl_link
[1] != prev
);
842 return (struct AVLNode
*)node
;
845 } /* AVL_FindPrevNodeByAddress */
847 /*****************************************************************************
851 AROS_LH3I(struct AVLNode
*, AVL_FindPrevNodeByKey
,
854 AROS_LHA(const struct AVLNode
*, root
, A0
),
855 AROS_LHA(AVLKey
, key
, A1
), AROS_LHA(AVLKEYCOMP
, func
, A2
),
857 struct ExecBase
*, SysBase
, 147, Exec
)
859 Find the node matching the key, or if such a node does not exist,
860 then the node with the next-lowest value.
863 Root - The root of the AVL tree.
865 key - The key to search.
867 func - The AVLKEYCOMP key comparision function for this tree.
870 A pointer to the struct AVLNode which matches this key, or
871 if that key is not present in the tree, the next lowest node.
872 Or NULL if key is lower than the key of any node in the tree.
875 This is only O(1.44log(n)) in the worst case.
882 AVL_AddNode(), AVL_FindNextNodeByAddress(), AVL_FindLastNode()
885 ******************************************************************************/
889 struct AVLNode
*node
= (struct AVLNode
*)root
;
890 struct AVLNode
*lesser
= NULL
;
893 while (node
!= NULL
&&
894 (cmp
= AROS_UFC2(LONG
, func
,
895 AROS_UFCA(const struct AVLNode
*, node
, A0
),
896 AROS_UFCA(AVLKey
, key
, A1
))) != 0)
900 node
= node
->avl_link
[cmp
< 0];
903 return (struct AVLNode
*)(node
!= NULL
? node
: lesser
);
906 } /* AVL_FindPrevNodeByKey */
908 /*****************************************************************************
912 AROS_LH1I(struct AVLNode
*, AVL_FindNextNodeByAddress
,
915 AROS_LHA(const struct AVLNode
*, Node
, A0
),
917 struct ExecBase
*, SysBase
, 148, Exec
)
919 Perform an in-order traversal to the next node in the tree.
922 Node - The current node. The node must be present in the tree.
925 The next-greatest node in the tree, or NULL if Node was already
926 the highest valued node in the tree.
929 This implementation uses a parent pointer to avoid needing
930 a stack or state to track it's current position in the tree.
932 Although this operation is typically O(1), in the worst case it
933 iterate the full depth of the tree - approximately 1.44Log(N).
936 ... in-order traversal of all nodes
937 node = (struct ExampleNode *)AVL_FindFirstNode(root);
939 printf(" %s\n", node->key);
940 node = (struct ExampleNode *)AVL_FindNextNodeByAddress(node);
943 ... in-order traversal of all nodes - with safe deletion
944 node = (struct ExampleNode *)AVL_FindFirstNode(root);
945 next = (struct ExampleNode *)AVL_FindNextNodeByAddress(node);
947 printf(" %s\n", node->key);
949 if (DELETE_NODE(node))
950 AVL_RemNodeByAddress(&root, node);
953 next = (struct ExampleNode *)AVL_FindNextNodeByAddress(node);
959 AVL_AddNode(), AVL_RemNodeByAddress(), AVL_FindFirstNode()
962 ******************************************************************************/
966 const struct AVLNode
*node
= (const struct AVLNode
*)Node
;
967 const struct AVLNode
*next
;
969 next
= node
->avl_link
[1];
975 next
= node
->avl_link
[0];
977 while (next
!= NULL
);
984 node
= node
->avl_parent
;
986 while (node
!= NULL
&& node
->avl_link
[1] == next
);
989 return (struct AVLNode
*)node
;
992 } /* AVL_FindNextNodeByAddress */
994 /*****************************************************************************
998 AROS_LH3I(struct AVLNode
*, AVL_FindNextNodeByKey
,
1001 AROS_LHA(const struct AVLNode
*, Root
, A0
),
1002 AROS_LHA(AVLKey
, key
, A1
), AROS_LHA(AVLKEYCOMP
, func
, A2
),
1004 struct ExecBase
*, SysBase
, 149, Exec
)
1006 Find the node matching the key, or if such a node does not exist,
1007 then the node with the next-highest value.
1010 Root - The root of the AVL tree.
1012 key - The key to search.
1014 func - The AVLKEYCOMP key comparision function for this tree.
1017 A pointer to the struct AVLNode which matches this key, or
1018 if that key is not present in the tree, the next highest node.
1019 Or NULL if key is higher than the key of any node in the tree.
1022 This is only O(1.44log(n)) in the worst case.
1029 AVL_AddNode(), AVL_FindNextNodeByAddress(), AVL_FindLastNode()
1032 ******************************************************************************/
1036 struct AVLNode
*node
= (struct AVLNode
*)Root
;
1037 struct AVLNode
*greater
= NULL
;
1040 while (node
!= NULL
&&
1041 (cmp
= AROS_UFC2(LONG
, func
,
1042 AROS_UFCA(const struct AVLNode
*, node
, A0
),
1043 AROS_UFCA(AVLKey
, key
, A1
))) != 0)
1047 node
= node
->avl_link
[cmp
< 0];
1050 return (struct AVLNode
*)(node
!= NULL
? node
: greater
);
1053 } /* AVL_FindNextNodeByKey */
1055 /*****************************************************************************
1059 AROS_LH1I(struct AVLNode
*, AVL_FindFirstNode
,
1062 AROS_LHA(const struct AVLNode
*, Root
, A0
),
1064 struct ExecBase
*, SysBase
, 150, Exec
)
1066 Find the smallest node in an AVL tree.
1069 Root - The root node of the AVL tree.
1072 NULL if the tree is empty (i.e. Root is NULL), or the node
1073 which contains the least value in the tree as determined by
1074 the comparision function used to add the node.
1077 AVL trees are balanced but not minimal. This operation
1078 must iterate the full depth of the tree on one side -
1079 approximately 1.44Log(N).
1082 See AVL_FindNextNodeByAddress()
1087 AVL_AddNode(), AVL_FindNextNodeByAddress()
1090 ******************************************************************************/
1094 struct AVLNode
*node
= (struct AVLNode
*)Root
;
1097 while (node
->avl_link
[0] != NULL
)
1098 node
= node
->avl_link
[0];
1100 return (struct AVLNode
*)node
;
1103 } /* AVL_FindFirstNode */
1105 /*****************************************************************************
1109 AROS_LH1I(struct AVLNode
*, AVL_FindLastNode
,
1112 AROS_LHA(const struct AVLNode
*, Root
, A0
),
1114 struct ExecBase
*, SysBase
, 151, Exec
)
1116 Find the largest node in an AVL tree.
1119 Root - The root node of the AVL tree.
1122 NULL if the tree is empty (i.e. Root is NULL), or the node
1123 which contains the greatest value in the tree as determined by
1124 the comparision function used to add the node.
1127 AVL trees are balanced but not minimal. This operation
1128 must iterate the full depth of the tree on one side -
1129 approximately 1.44Log(N).
1132 See AVL_FindPrevNodeByAddress()
1137 AVL_AddNode(), AVL_FindPrevNodeByAddress()
1140 ******************************************************************************/
1144 struct AVLNode
*node
= (struct AVLNode
*)Root
;
1147 while (node
->avl_link
[1] != NULL
)
1148 node
= node
->avl_link
[1];
1150 return (struct AVLNode
*)node
;
1153 } /* AVL_FindLastNode */