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