xref: /illumos-gate/usr/src/uts/common/sys/avl.h (revision 7c478bd95313f5f23a4c958a745db2134aa0324)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #ifndef	_AVL_H
28*7c478bd9Sstevel@tonic-gate #define	_AVL_H
29*7c478bd9Sstevel@tonic-gate 
30*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
31*7c478bd9Sstevel@tonic-gate 
32*7c478bd9Sstevel@tonic-gate /*
33*7c478bd9Sstevel@tonic-gate  * This is a private header file.  Applications should not directly include
34*7c478bd9Sstevel@tonic-gate  * this file.
35*7c478bd9Sstevel@tonic-gate  */
36*7c478bd9Sstevel@tonic-gate 
37*7c478bd9Sstevel@tonic-gate #ifdef	__cplusplus
38*7c478bd9Sstevel@tonic-gate extern "C" {
39*7c478bd9Sstevel@tonic-gate #endif
40*7c478bd9Sstevel@tonic-gate 
41*7c478bd9Sstevel@tonic-gate #include <sys/avl_impl.h>
42*7c478bd9Sstevel@tonic-gate 
43*7c478bd9Sstevel@tonic-gate /*
44*7c478bd9Sstevel@tonic-gate  * This is a generic implemenatation of AVL trees for use in the Solaris kernel.
45*7c478bd9Sstevel@tonic-gate  * The interfaces provide an efficient way of implementing an ordered set of
46*7c478bd9Sstevel@tonic-gate  * data structures.
47*7c478bd9Sstevel@tonic-gate  *
48*7c478bd9Sstevel@tonic-gate  * AVL trees provide an alternative to using an ordered linked list. Using AVL
49*7c478bd9Sstevel@tonic-gate  * trees will usually be faster, however they requires more storage. An ordered
50*7c478bd9Sstevel@tonic-gate  * linked list in general requires 2 pointers in each data structure. The
51*7c478bd9Sstevel@tonic-gate  * AVL tree implementation uses 3 pointers. The following chart gives the
52*7c478bd9Sstevel@tonic-gate  * approximate performance of operations with the different approaches:
53*7c478bd9Sstevel@tonic-gate  *
54*7c478bd9Sstevel@tonic-gate  *	Operation	 Link List	AVL tree
55*7c478bd9Sstevel@tonic-gate  *	---------	 --------	--------
56*7c478bd9Sstevel@tonic-gate  *	lookup		   O(n)		O(log(n))
57*7c478bd9Sstevel@tonic-gate  *
58*7c478bd9Sstevel@tonic-gate  *	insert 1 node	 constant	constant
59*7c478bd9Sstevel@tonic-gate  *
60*7c478bd9Sstevel@tonic-gate  *	delete 1 node	 constant	between constant and O(log(n))
61*7c478bd9Sstevel@tonic-gate  *
62*7c478bd9Sstevel@tonic-gate  *	delete all nodes   O(n)		O(n)
63*7c478bd9Sstevel@tonic-gate  *
64*7c478bd9Sstevel@tonic-gate  *	visit the next
65*7c478bd9Sstevel@tonic-gate  *	or prev node	 constant	between constant and O(log(n))
66*7c478bd9Sstevel@tonic-gate  *
67*7c478bd9Sstevel@tonic-gate  *
68*7c478bd9Sstevel@tonic-gate  * The data structure nodes are anchored at an "avl_tree_t" (the equivalent
69*7c478bd9Sstevel@tonic-gate  * of a list header) and the individual nodes will have a field of
70*7c478bd9Sstevel@tonic-gate  * type "avl_node_t" (corresponding to list pointers).
71*7c478bd9Sstevel@tonic-gate  *
72*7c478bd9Sstevel@tonic-gate  * The type "avl_index_t" is used to indicate a position in the list for
73*7c478bd9Sstevel@tonic-gate  * certain calls.
74*7c478bd9Sstevel@tonic-gate  *
75*7c478bd9Sstevel@tonic-gate  * The usage scenario is generally:
76*7c478bd9Sstevel@tonic-gate  *
77*7c478bd9Sstevel@tonic-gate  * 1. Create the list/tree with: avl_create()
78*7c478bd9Sstevel@tonic-gate  *
79*7c478bd9Sstevel@tonic-gate  * followed by any mixture of:
80*7c478bd9Sstevel@tonic-gate  *
81*7c478bd9Sstevel@tonic-gate  * 2a. Insert nodes with: avl_find() and avl_insert()
82*7c478bd9Sstevel@tonic-gate  *
83*7c478bd9Sstevel@tonic-gate  * 2b. Visited elements with:
84*7c478bd9Sstevel@tonic-gate  *	 avl_first() - returns the lowest valued node
85*7c478bd9Sstevel@tonic-gate  *	 avl_last() - returns the highest valued node
86*7c478bd9Sstevel@tonic-gate  *	 AVL_NEXT() - given a node go to next higher one
87*7c478bd9Sstevel@tonic-gate  *	 AVL_PREV() - given a node go to previous lower one
88*7c478bd9Sstevel@tonic-gate  *
89*7c478bd9Sstevel@tonic-gate  * 2c.  Find the node with the closest value either less than or greater
90*7c478bd9Sstevel@tonic-gate  *	than a given value with avl_nearest().
91*7c478bd9Sstevel@tonic-gate  *
92*7c478bd9Sstevel@tonic-gate  * 2d. Remove individual nodes from the list/tree with avl_remove.
93*7c478bd9Sstevel@tonic-gate  *
94*7c478bd9Sstevel@tonic-gate  * and finally when the list is being destroyed
95*7c478bd9Sstevel@tonic-gate  *
96*7c478bd9Sstevel@tonic-gate  * 3. Use avl_destroy_nodes() to quickly process/free up any remaining nodes.
97*7c478bd9Sstevel@tonic-gate  *    Note that once you use avl_destroy_nodes(), you can no longer
98*7c478bd9Sstevel@tonic-gate  *    use any routine except avl_destroy_nodes() and avl_destoy().
99*7c478bd9Sstevel@tonic-gate  *
100*7c478bd9Sstevel@tonic-gate  * 4. Use avl_destroy() to destroy the AVL tree itself.
101*7c478bd9Sstevel@tonic-gate  *
102*7c478bd9Sstevel@tonic-gate  * Any locking for multiple thread access is up to the user to provide, just
103*7c478bd9Sstevel@tonic-gate  * as is needed for any linked list implementation.
104*7c478bd9Sstevel@tonic-gate  */
105*7c478bd9Sstevel@tonic-gate 
106*7c478bd9Sstevel@tonic-gate 
107*7c478bd9Sstevel@tonic-gate /*
108*7c478bd9Sstevel@tonic-gate  * Type used for the root of the AVL tree.
109*7c478bd9Sstevel@tonic-gate  */
110*7c478bd9Sstevel@tonic-gate typedef struct avl_tree avl_tree_t;
111*7c478bd9Sstevel@tonic-gate 
112*7c478bd9Sstevel@tonic-gate /*
113*7c478bd9Sstevel@tonic-gate  * The data nodes in the AVL tree must have a field of this type.
114*7c478bd9Sstevel@tonic-gate  */
115*7c478bd9Sstevel@tonic-gate typedef struct avl_node avl_node_t;
116*7c478bd9Sstevel@tonic-gate 
117*7c478bd9Sstevel@tonic-gate /*
118*7c478bd9Sstevel@tonic-gate  * An opaque type used to locate a position in the tree where a node
119*7c478bd9Sstevel@tonic-gate  * would be inserted.
120*7c478bd9Sstevel@tonic-gate  */
121*7c478bd9Sstevel@tonic-gate typedef uintptr_t avl_index_t;
122*7c478bd9Sstevel@tonic-gate 
123*7c478bd9Sstevel@tonic-gate 
124*7c478bd9Sstevel@tonic-gate /*
125*7c478bd9Sstevel@tonic-gate  * Direction constants used for avl_nearest().
126*7c478bd9Sstevel@tonic-gate  */
127*7c478bd9Sstevel@tonic-gate #define	AVL_BEFORE	(0)
128*7c478bd9Sstevel@tonic-gate #define	AVL_AFTER	(1)
129*7c478bd9Sstevel@tonic-gate 
130*7c478bd9Sstevel@tonic-gate 
131*7c478bd9Sstevel@tonic-gate 
132*7c478bd9Sstevel@tonic-gate /*
133*7c478bd9Sstevel@tonic-gate  * Prototypes
134*7c478bd9Sstevel@tonic-gate  *
135*7c478bd9Sstevel@tonic-gate  * Where not otherwise mentioned, "void *" arguments are a pointer to the
136*7c478bd9Sstevel@tonic-gate  * user data structure which must contain a field of type avl_node_t.
137*7c478bd9Sstevel@tonic-gate  *
138*7c478bd9Sstevel@tonic-gate  * Also assume the user data structures looks like:
139*7c478bd9Sstevel@tonic-gate  *	stuct my_type {
140*7c478bd9Sstevel@tonic-gate  *		...
141*7c478bd9Sstevel@tonic-gate  *		avl_node_t	my_link;
142*7c478bd9Sstevel@tonic-gate  *		...
143*7c478bd9Sstevel@tonic-gate  *	};
144*7c478bd9Sstevel@tonic-gate  */
145*7c478bd9Sstevel@tonic-gate 
146*7c478bd9Sstevel@tonic-gate /*
147*7c478bd9Sstevel@tonic-gate  * Initialize an AVL tree. Arguments are:
148*7c478bd9Sstevel@tonic-gate  *
149*7c478bd9Sstevel@tonic-gate  * tree   - the tree to be initialized
150*7c478bd9Sstevel@tonic-gate  * compar - function to compare two nodes, it must return exactly: -1, 0, or +1
151*7c478bd9Sstevel@tonic-gate  *          -1 for <, 0 for ==, and +1 for >
152*7c478bd9Sstevel@tonic-gate  * size   - the value of sizeof(struct my_type)
153*7c478bd9Sstevel@tonic-gate  * offset - the value of OFFSETOF(struct my_type, my_link)
154*7c478bd9Sstevel@tonic-gate  */
155*7c478bd9Sstevel@tonic-gate extern void avl_create(avl_tree_t *tree,
156*7c478bd9Sstevel@tonic-gate 	int (*compar) (const void *, const void *), size_t size, size_t offset);
157*7c478bd9Sstevel@tonic-gate 
158*7c478bd9Sstevel@tonic-gate 
159*7c478bd9Sstevel@tonic-gate /*
160*7c478bd9Sstevel@tonic-gate  * Find a node with a matching value in the tree. Returns the matching node
161*7c478bd9Sstevel@tonic-gate  * found. If not found, it returns NULL and then if "where" is not NULL it sets
162*7c478bd9Sstevel@tonic-gate  * "where" for use with avl_insert() or avl_nearest().
163*7c478bd9Sstevel@tonic-gate  *
164*7c478bd9Sstevel@tonic-gate  * node   - node that has the value being looked for
165*7c478bd9Sstevel@tonic-gate  * where  - position for use with avl_nearest() or avl_insert(), may be NULL
166*7c478bd9Sstevel@tonic-gate  */
167*7c478bd9Sstevel@tonic-gate extern void *avl_find(avl_tree_t *tree, void *node, avl_index_t *where);
168*7c478bd9Sstevel@tonic-gate 
169*7c478bd9Sstevel@tonic-gate /*
170*7c478bd9Sstevel@tonic-gate  * Insert a node into the tree.
171*7c478bd9Sstevel@tonic-gate  *
172*7c478bd9Sstevel@tonic-gate  * node   - the node to insert
173*7c478bd9Sstevel@tonic-gate  * where  - position as returned from avl_find()
174*7c478bd9Sstevel@tonic-gate  */
175*7c478bd9Sstevel@tonic-gate extern void avl_insert(avl_tree_t *tree, void *node, avl_index_t where);
176*7c478bd9Sstevel@tonic-gate 
177*7c478bd9Sstevel@tonic-gate /*
178*7c478bd9Sstevel@tonic-gate  * Insert "new_data" in "tree" in the given "direction" either after
179*7c478bd9Sstevel@tonic-gate  * or before the data "here".
180*7c478bd9Sstevel@tonic-gate  *
181*7c478bd9Sstevel@tonic-gate  * This might be usefull for avl clients caching recently accessed
182*7c478bd9Sstevel@tonic-gate  * data to avoid doing avl_find() again for insertion.
183*7c478bd9Sstevel@tonic-gate  *
184*7c478bd9Sstevel@tonic-gate  * new_data	- new data to insert
185*7c478bd9Sstevel@tonic-gate  * here  	- existing node in "tree"
186*7c478bd9Sstevel@tonic-gate  * direction	- either AVL_AFTER or AVL_BEFORE the data "here".
187*7c478bd9Sstevel@tonic-gate  */
188*7c478bd9Sstevel@tonic-gate extern void avl_insert_here(avl_tree_t *tree, void *new_data, void *here,
189*7c478bd9Sstevel@tonic-gate     int direction);
190*7c478bd9Sstevel@tonic-gate 
191*7c478bd9Sstevel@tonic-gate 
192*7c478bd9Sstevel@tonic-gate /*
193*7c478bd9Sstevel@tonic-gate  * Return the first or last valued node in the tree. Will return NULL
194*7c478bd9Sstevel@tonic-gate  * if the tree is empty.
195*7c478bd9Sstevel@tonic-gate  *
196*7c478bd9Sstevel@tonic-gate  */
197*7c478bd9Sstevel@tonic-gate extern void *avl_first(avl_tree_t *tree);
198*7c478bd9Sstevel@tonic-gate extern void *avl_last(avl_tree_t *tree);
199*7c478bd9Sstevel@tonic-gate 
200*7c478bd9Sstevel@tonic-gate 
201*7c478bd9Sstevel@tonic-gate /*
202*7c478bd9Sstevel@tonic-gate  * Return the next or previous valued node in the tree.
203*7c478bd9Sstevel@tonic-gate  * AVL_NEXT() will return NULL if at the last node.
204*7c478bd9Sstevel@tonic-gate  * AVL_PREV() will return NULL if at the first node.
205*7c478bd9Sstevel@tonic-gate  *
206*7c478bd9Sstevel@tonic-gate  * node   - the node from which the next or previous node is found
207*7c478bd9Sstevel@tonic-gate  */
208*7c478bd9Sstevel@tonic-gate #define	AVL_NEXT(tree, node)	avl_walk(tree, node, AVL_AFTER)
209*7c478bd9Sstevel@tonic-gate #define	AVL_PREV(tree, node)	avl_walk(tree, node, AVL_BEFORE)
210*7c478bd9Sstevel@tonic-gate 
211*7c478bd9Sstevel@tonic-gate 
212*7c478bd9Sstevel@tonic-gate /*
213*7c478bd9Sstevel@tonic-gate  * Find the node with the nearest value either greater or less than
214*7c478bd9Sstevel@tonic-gate  * the value from a previous avl_find(). Returns the node or NULL if
215*7c478bd9Sstevel@tonic-gate  * there isn't a matching one.
216*7c478bd9Sstevel@tonic-gate  *
217*7c478bd9Sstevel@tonic-gate  * where     - position as returned from avl_find()
218*7c478bd9Sstevel@tonic-gate  * direction - either AVL_BEFORE or AVL_AFTER
219*7c478bd9Sstevel@tonic-gate  *
220*7c478bd9Sstevel@tonic-gate  * EXAMPLE get the greatest node that is less than a given value:
221*7c478bd9Sstevel@tonic-gate  *
222*7c478bd9Sstevel@tonic-gate  *	avl_tree_t *tree;
223*7c478bd9Sstevel@tonic-gate  *	struct my_data look_for_value = {....};
224*7c478bd9Sstevel@tonic-gate  *	struct my_data *node;
225*7c478bd9Sstevel@tonic-gate  *	struct my_data *less;
226*7c478bd9Sstevel@tonic-gate  *	avl_index_t where;
227*7c478bd9Sstevel@tonic-gate  *
228*7c478bd9Sstevel@tonic-gate  *	node = avl_find(tree, &look_for_value, &where);
229*7c478bd9Sstevel@tonic-gate  *	if (node != NULL)
230*7c478bd9Sstevel@tonic-gate  *		less = AVL_PREV(tree, node);
231*7c478bd9Sstevel@tonic-gate  *	else
232*7c478bd9Sstevel@tonic-gate  *		less = avl_nearest(tree, where, AVL_BEFORE);
233*7c478bd9Sstevel@tonic-gate  */
234*7c478bd9Sstevel@tonic-gate extern void *avl_nearest(avl_tree_t *tree, avl_index_t where, int direction);
235*7c478bd9Sstevel@tonic-gate 
236*7c478bd9Sstevel@tonic-gate 
237*7c478bd9Sstevel@tonic-gate /*
238*7c478bd9Sstevel@tonic-gate  * Remove a single node from the tree.
239*7c478bd9Sstevel@tonic-gate  *
240*7c478bd9Sstevel@tonic-gate  * node   - the node to remove
241*7c478bd9Sstevel@tonic-gate  */
242*7c478bd9Sstevel@tonic-gate extern void avl_remove(avl_tree_t *tree, void *node);
243*7c478bd9Sstevel@tonic-gate 
244*7c478bd9Sstevel@tonic-gate 
245*7c478bd9Sstevel@tonic-gate /*
246*7c478bd9Sstevel@tonic-gate  * Return the number of nodes in the tree
247*7c478bd9Sstevel@tonic-gate  */
248*7c478bd9Sstevel@tonic-gate extern ulong_t avl_numnodes(avl_tree_t *tree);
249*7c478bd9Sstevel@tonic-gate 
250*7c478bd9Sstevel@tonic-gate 
251*7c478bd9Sstevel@tonic-gate /*
252*7c478bd9Sstevel@tonic-gate  * Used to destroy any remaining nodes in a tree. The cookie argument should
253*7c478bd9Sstevel@tonic-gate  * be initialized to NULL before the first call. Returns a node that has been
254*7c478bd9Sstevel@tonic-gate  * removed from the tree and may be free()'d. Returns NULL when the tree is
255*7c478bd9Sstevel@tonic-gate  * empty.
256*7c478bd9Sstevel@tonic-gate  *
257*7c478bd9Sstevel@tonic-gate  * Once you call avl_destroy_nodes(), you can only continuing calling it and
258*7c478bd9Sstevel@tonic-gate  * finally avl_destroy(). No other AVL routines will be valid.
259*7c478bd9Sstevel@tonic-gate  *
260*7c478bd9Sstevel@tonic-gate  * cookie - a "void *" used to save state between calls to avl_destroy_nodes()
261*7c478bd9Sstevel@tonic-gate  *
262*7c478bd9Sstevel@tonic-gate  * EXAMPLE:
263*7c478bd9Sstevel@tonic-gate  *	avl_tree_t *tree;
264*7c478bd9Sstevel@tonic-gate  *	struct my_data *node;
265*7c478bd9Sstevel@tonic-gate  *	void *cookie;
266*7c478bd9Sstevel@tonic-gate  *
267*7c478bd9Sstevel@tonic-gate  *	cookie = NULL;
268*7c478bd9Sstevel@tonic-gate  *	while ((node = avl_destroy_nodes(tree, &cookie)) != NULL)
269*7c478bd9Sstevel@tonic-gate  *		free(node);
270*7c478bd9Sstevel@tonic-gate  *	avl_destroy(tree);
271*7c478bd9Sstevel@tonic-gate  */
272*7c478bd9Sstevel@tonic-gate extern void *avl_destroy_nodes(avl_tree_t *tree, void **cookie);
273*7c478bd9Sstevel@tonic-gate 
274*7c478bd9Sstevel@tonic-gate 
275*7c478bd9Sstevel@tonic-gate /*
276*7c478bd9Sstevel@tonic-gate  * Final destroy of an AVL tree. Arguments are:
277*7c478bd9Sstevel@tonic-gate  *
278*7c478bd9Sstevel@tonic-gate  * tree   - the empty tree to destroy
279*7c478bd9Sstevel@tonic-gate  */
280*7c478bd9Sstevel@tonic-gate extern void avl_destroy(avl_tree_t *tree);
281*7c478bd9Sstevel@tonic-gate 
282*7c478bd9Sstevel@tonic-gate 
283*7c478bd9Sstevel@tonic-gate 
284*7c478bd9Sstevel@tonic-gate #ifdef	__cplusplus
285*7c478bd9Sstevel@tonic-gate }
286*7c478bd9Sstevel@tonic-gate #endif
287*7c478bd9Sstevel@tonic-gate 
288*7c478bd9Sstevel@tonic-gate #endif	/* _AVL_H */
289