2 .\" This file and its contents are supplied under the terms of the
3 .\" Common Development and Distribution License ("CDDL"), version 1.0.
4 .\" You may only use this file in accordance with the terms of version
7 .\" A full copy of the text of the CDDL should have accompanied this
8 .\" source. A copy of the CDDL is also available via the Internet at
9 .\" http://www.illumos.org/license/CDDL.
12 .\" Copyright 2015 Joyent, Inc.
19 .Nd generic self-balancing binary search tree library
26 library provides a generic implementation of AVL trees, a form of
27 self-balancing binary tree.
28 The interfaces provided allow for an efficient way of implementing an ordered
29 set of data structures and, due to its embeddable nature, allow for a single
30 instance of a data structure to belong to multiple AVL trees.
32 Each AVL tree contains entries of a single type of data structure.
33 Rather than allocating memory for pointers for those data structures,
34 the storage for the tree is embedded into the data structures by
35 declaring a member of type
37 When an AVL tree is created, through the use of
39 it encodes the size of the data structure, the offset of the data
40 structure, and a comparator function which is used to compare two
41 instances of a data structure.
42 A data structure may be a member of multiple AVL trees by creating AVL trees
43 which use different offsets (different members) into the data structure.
45 AVL trees support both look up of an arbitrary item and ordered
46 iteration over the contents of the entire tree.
47 In addition, from any node, you can find the previous and next entries in the
49 In addition, AVL trees support arbitrary insertion and deletion.
51 AVL trees are often used in place of linked lists.
52 Compared to the standard, intrusive, doubly linked list, it has the following
53 performance characteristics:
55 .It Sy Lookup One Node
57 Lookup of a single node in a linked list is
59 whereas lookup of a single node in an AVL tree is
62 .It Sy Insert One Node
64 Inserting a single node into a linked list is
66 Inserting a single node into an AVL tree is
69 Note, insertions into an AVL tree always result in an ordered tree.
70 Insertions into a linked list do not guarantee order.
71 If order is required, then the time to do the insertion into a linked list will
72 depend on the time of the search algorithm being employed to find the place to
75 .It Sy Delete One Node
77 Deleting a single node from a linked list is
79 whereas deleting a single node from an AVL tree takes
83 .It Sy Delete All Nodes
85 Deleting all nodes from a linked list is
87 With an AVL tree, if using the
88 .Xr avl_destroy_nodes 3AVL
89 function then deleting all nodes
92 However, if iterating over each entry in the tree and then removing it using
97 then the time to remove all nodes is
100 .It Sy Visit the Next or Previous Node
102 Visiting the next or previous node in a linked list is
104 whereas going from the next to the previous node in an AVL tree will
112 In general, AVL trees are a good alternative for linked lists when order
113 or lookup speed is important and a reasonable number of items will be
118 provides the public interfaces defined below.
121 for additional information on shared object interfaces.
122 Individual functions are documented in their own manual pages.
123 .Bl -column -offset indent ".Sy avl_is_empty" ".Sy avl_destroy_nodes"
124 .It Sy avl_add Ta Sy avl_create
125 .It Sy avl_destroy Ta Sy avl_destroy_nodes
126 .It Sy avl_find Ta Sy avl_first
127 .It Sy avl_insert Ta Sy avl_insert_here
128 .It Sy avl_is_empty Ta Sy avl_last
129 .It Sy avl_nearest Ta Sy avl_numnodes
130 .It Sy avl_remove Ta Sy avl_swap
133 In addition, the library defines C pre-processor macros which are
134 defined below and documented in their own manual pages.
136 .\" Use the same column widths in both cases where we describe the list
137 .\" of interfaces, to allow the manual page to better line up when rendered.
139 .Bl -column -offset indent ".Sy avl_is_empty" ".Sy avl_destroy_nodes"
140 .It Sy AVL_NEXT Ta Sy AVL_PREV
145 library defines the following types:
149 Type used for the root of the AVL tree.
150 Consumers define one of these for each of the different trees that they want to
155 Type used as the data node for an AVL tree.
156 One of these is embedded in each data structure that is the member of an AVL
161 Type used to locate a position in a tree.
165 .Xr avl_insert 3AVL .
169 library provides no locking.
170 Callers that are using the same AVL tree from multiple threads need to provide
171 their own synchronization.
172 If only one thread is ever accessing or modifying the AVL tree, then there are
173 no synchronization concerns.
174 If multiple AVL trees exist, then they may all be used simultaneously; however,
175 they are subject to the same rules around simultaneous access from a single
178 All routines are both
181 .Sy Async-Signal-Safe .
182 Callers may call functions in
184 from a signal handler and
186 calls are all safe in face of
188 however, if callers have their own locks, then they must make sure that
189 they are accounted for by the use of routines such as
190 .Xr pthread_atfork 3C .
192 The following code shows examples of exercising all of the functionality
195 It can be compiled by using a C compiler and linking
198 For example, given a file named avl.c, with gcc, one would run:
200 $ gcc -Wall -o avl avl.c -lavl
204 * Example of using AVL Trees
212 static avl_tree_t inttree;
215 * The structure that we're storing in an AVL tree.
217 typedef struct intnode {
223 intnode_comparator(const void *l, const void *r)
225 const intnode_t *li = l;
226 const intnode_t *ri = r;
228 if (li->in_val > ri->in_val)
230 if (li->in_val < ri->in_val)
241 avl_create(&inttree, intnode_comparator, sizeof (intnode_t),
242 offsetof(intnode_t, in_avl));
246 * Add entries to the tree with the avl_add function.
254 for (i = 0; i < 20; i++) {
255 inp = malloc(sizeof (intnode_t));
258 avl_add(&inttree, inp);
263 * Find entries in the AVL tree. Note, we create an intnode_t on the
264 * stack that we use to look this up.
270 intnode_t lookup, *inp;
272 for (i = 10; i < 30; i++) {
274 inp = avl_find(&inttree, &lookup, NULL);
276 printf("Entry %d is not in the tree\\n", i);
278 printf("Entry %d is in the tree\\n",
285 * Walk the tree forwards
291 for (inp = avl_first(&inttree); inp != NULL;
292 inp = AVL_NEXT(&inttree, inp)) {
293 printf("Found entry %d\\n", inp->in_val);
298 * Walk the tree backwards.
304 for (inp = avl_last(&inttree); inp != NULL;
305 inp = AVL_PREV(&inttree, inp)) {
306 printf("Found entry %d\\n", inp->in_val);
311 * Determine the number of nodes in the tree and if it is empty or
315 inttree_inspect(void)
317 printf("The tree is %s, there are %ld nodes in it\\n",
318 avl_is_empty(&inttree) == B_TRUE ? "empty" : "not empty",
319 avl_numnodes(&inttree));
323 * Use avl_remove to remove entries from the tree.
329 intnode_t lookup, *inp;
331 for (i = 0; i < 20; i+= 4) {
333 inp = avl_find(&inttree, &lookup, NULL);
335 avl_remove(&inttree, inp);
340 * Find the nearest nodes in the tree.
345 intnode_t lookup, *inp;
349 if (avl_find(&inttree, &lookup, &where) != NULL)
351 inp = avl_nearest(&inttree, where, AVL_BEFORE);
353 printf("closest node before 12 is: %d\\n", inp->in_val);
354 inp = avl_nearest(&inttree, where, AVL_AFTER);
356 printf("closest node after 12 is: %d\\n", inp->in_val);
362 intnode_t lookup, *inp;
366 if (avl_find(&inttree, &lookup, &where) != NULL)
368 inp = malloc(sizeof (intnode_t));
370 avl_insert(&inttree, inp, where);
378 avl_create(&swap, intnode_comparator, sizeof (intnode_t),
379 offsetof(intnode_t, in_avl));
380 avl_swap(&inttree, &swap);
382 avl_swap(&inttree, &swap);
387 * Remove all remaining nodes in the tree. We first use
388 * avl_destroy_nodes to empty the tree, then avl_destroy to finish.
396 while ((inp = avl_destroy_nodes(&inttree, &c)) != NULL) {
399 avl_destroy(&inttree);
422 .Sh INTERFACE STABILITY
429 .Xr pthread_atfork 3C
432 .Xr avl_create 3AVL ,
433 .Xr avl_destroy 3AVL ,
434 .Xr avl_destroy_nodes 3AVL ,
437 .Xr avl_insert 3AVL ,
438 .Xr avl_insert_here 3AVL ,
439 .Xr avl_is_empty 3AVL ,
441 .Xr avl_nearest 3AVL ,
442 .Xr avl_numnodes 3AVL ,
443 .Xr avl_remove 3AVL ,
446 .%A Adel'son-Vel'skiy, G. M.
448 .%T "An Algorithm for the Organization of Information"
449 .%Q Deklady Akademii Nauk