libdict 1.0.7
Data Structure C Library
Loading...
Searching...
No Matches
sp_tree.c
Go to the documentation of this file.
1/*
2 * libdict -- splay tree implementation.
3 *
4 * Copyright (c) 2001-2014, Farooq Mela
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
20 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28/*
29 * cf. [Sleator and Tarjan, 1985], [Tarjan 1985], [Tarjan 1983]
30 *
31 * A single operation on a splay tree has a worst-case time complexity of O(N),
32 * but a series of M operations have a time complexity of O(M lg N), and thus
33 * the amortized time complexity of an operation is O(lg N). More specifically,
34 * a series of M operations on a tree with N nodes will run in O((N+M)lg(N+M))
35 * time. Splay trees work by "splaying" a node up the tree using a series of
36 * rotations until it is the root each time it is accessed. They are much
37 * simpler to code than most balanced trees, because there is no strict
38 * requirement about maintaining a balance scheme among nodes. When inserting
39 * and searching, we simply splay the node in question up until it becomes the
40 * root of the tree.
41 *
42 * This implementation is a bottom-up, move-to-root splay tree.
43 */
44
45/* TODO: rather than splay after the fact, use the splay operation to traverse
46 * the tree during insert, search, delete, etc. */
47
48#include "sp_tree.h"
49
50#include "dict_private.h"
51#include "tree_common.h"
52
53typedef struct sp_node sp_node;
57
61
65
66/* Vtable thunks. The vtable slot types take void*, and calling a function
67 * through a function-pointer type that is not compatible with the function's
68 * own type is undefined behaviour (C11 6.5.2.2p9), so each slot below gets a
69 * thunk with the exact slot signature instead of a cast. A cast would also
70 * hide a genuine signature mismatch. */
71static dict_itor* vt_sp_dict_itor_new(void* obj) { return sp_dict_itor_new(obj); }
72static dict_insert_result vt_sp_tree_insert(void* obj, void* key) { return sp_tree_insert(obj, key); }
73static void** vt_sp_tree_search(void* obj, const void* key) { return sp_tree_search(obj, key); }
74static void** vt_sp_tree_search_le(void* obj, const void* key) { return sp_tree_search_le(obj, key); }
75static void** vt_sp_tree_search_lt(void* obj, const void* key) { return sp_tree_search_lt(obj, key); }
76static void** vt_sp_tree_search_ge(void* obj, const void* key) { return sp_tree_search_ge(obj, key); }
77static void** vt_sp_tree_search_gt(void* obj, const void* key) { return sp_tree_search_gt(obj, key); }
78static dict_remove_result vt_sp_tree_remove(void* obj, const void* key) { return sp_tree_remove(obj, key); }
79static bool vt_sp_tree_verify(const void* obj) { return sp_tree_verify(obj); }
80static bool vt_sp_itor_search(void* itor, const void* key) { return sp_itor_search(itor, key); }
81static bool vt_sp_itor_remove(void* itor) { return sp_itor_remove(itor); }
82
83static const dict_vtable sp_tree_vtable = {
84 true,
85 vt_sp_dict_itor_new,
87 vt_sp_tree_insert,
88 vt_sp_tree_search,
89 vt_sp_tree_search_le,
90 vt_sp_tree_search_lt,
91 vt_sp_tree_search_ge,
92 vt_sp_tree_search_gt,
93 vt_sp_tree_remove,
98 vt_sp_tree_verify,
99};
100
101static const itor_vtable sp_tree_itor_vtable = {
113 vt_sp_itor_search,
118 vt_sp_itor_remove,
120};
121
122static sp_node* node_new(void* key);
123static void splay(sp_tree* t, sp_node* n);
124
125sp_tree*
127{
128 ASSERT(cmp_func != NULL);
129
130 sp_tree* tree = MALLOC(sizeof(*tree));
131 if (tree) {
132 tree->root = NULL;
133 tree->count = 0;
134 tree->cmp_func = cmp_func;
135 tree->rotation_count = 0;
136 }
137 return tree;
138}
139
140dict*
142{
143 dict* dct = MALLOC(sizeof(*dct));
144 if (dct) {
145 if (!(dct->_object = sp_tree_new(cmp_func))) {
146 FREE(dct);
147 return NULL;
148 }
149 dct->_vtable = &sp_tree_vtable;
150 }
151 return dct;
152}
153
154size_t sp_tree_free(sp_tree* tree, dict_delete_func delete_func) { return tree_free(tree, delete_func); }
155size_t sp_tree_clear(sp_tree* tree, dict_delete_func delete_func) { return tree_clear(tree, delete_func); }
156
157static void
158splay(sp_tree* t, sp_node* n)
159{
160 unsigned rotations = 0;
161 for (;;) {
162 sp_node* p = n->parent;
163 if (!p)
164 break;
165
166 sp_node* pp = p->parent;
167 if (!pp) {
168 /* Parent is the root; simply rotate root left or right so that |n|
169 * becomes new root. */
170 if (p->llink == n) {
171 if ((p->llink = n->rlink) != NULL)
172 p->llink->parent = p;
173 n->rlink = p;
174 } else {
175 if ((p->rlink = n->llink) != NULL)
176 p->rlink->parent = p;
177 n->llink = p;
178 }
179 p->parent = n;
180 t->root = n;
181 n->parent = NULL;
182 rotations += 1;
183 break;
184 }
185
186 rotations += 2;
187 sp_node* ppp = pp->parent;
188 if (p->llink == n) {
189 if (pp->llink == p) {
190 /* Rotate parent right, then node right. */
191 sp_node* const pr = p->rlink;
192 p->rlink = pp;
193 pp->parent = p;
194 if ((pp->llink = pr) != NULL)
195 pr->parent = pp;
196
197 sp_node* const nr = n->rlink;
198 n->rlink = p;
199 p->parent = n;
200 if ((p->llink = nr) != NULL)
201 nr->parent = p;
202 } else {
203 /* Rotate node right, then parent left. */
204 sp_node* const nr = n->rlink;
205 n->rlink = p;
206 p->parent = n;
207 if ((p->llink = nr) != NULL)
208 nr->parent = p;
209
210 sp_node* const nl = n->llink;
211 n->llink = pp;
212 pp->parent = n;
213 if ((pp->rlink = nl) != NULL)
214 nl->parent = pp;
215 }
216 } else {
217 if (pp->rlink == p) {
218 /* Rotate parent left, then node left. */
219 sp_node* const pl = p->llink;
220 p->llink = pp;
221 pp->parent = p;
222 if ((pp->rlink = pl) != NULL)
223 pl->parent = pp;
224
225 sp_node* const nl = n->llink;
226 n->llink = p;
227 p->parent = n;
228 if ((p->rlink = nl) != NULL)
229 nl->parent = p;
230 } else {
231 /* Rotate node left, then parent right. */
232 sp_node* const nl = n->llink;
233 n->llink = p;
234 p->parent = n;
235 if ((p->rlink = nl) != NULL)
236 nl->parent = p;
237
238 sp_node* const nr = n->rlink;
239 n->rlink = pp;
240 pp->parent = n;
241 if ((pp->llink = nr) != NULL)
242 nr->parent = pp;
243 }
244 }
245 n->parent = ppp;
246 if (ppp) {
247 if (ppp->llink == pp)
248 ppp->llink = n;
249 else
250 ppp->rlink = n;
251 } else {
252 t->root = n;
253 break;
254 }
255 }
256 t->rotation_count += rotations;
257}
258
261{
262 int cmp = 0;
263 sp_node* node = tree->root;
264 sp_node* parent = NULL;
265 while (node) {
266 cmp = tree->cmp_func(key, node->key);
267 if (cmp < 0) {
268 parent = node; node = node->llink;
269 } else if (cmp > 0) {
270 parent = node; node = node->rlink;
271 } else {
272 /* Splay on a duplicate too: every other accessor restructures, and
273 * skipping it here breaks the amortized O(lg n) bound for repeated
274 * inserts of an existing key. */
275 splay(tree, node);
276 return (dict_insert_result) { &node->datum, false };
277 }
278 }
279
280 if (!(node = node_new(key)))
281 return (dict_insert_result) { NULL, false };
282
283 if (!(node->parent = parent)) {
284 ASSERT(tree->count == 0);
285 ASSERT(tree->root == NULL);
286 tree->root = node;
287 tree->count = 1;
288 } else {
289 if (cmp < 0)
290 parent->llink = node;
291 else
292 parent->rlink = node;
293 splay(tree, node);
294 tree->count++;
295 }
296 ASSERT(tree->root == node);
297 return (dict_insert_result) { &node->datum, true };
298}
299
300void**
301sp_tree_search(sp_tree* tree, const void* key)
302{
303 sp_node* parent = NULL;
304 for (sp_node* node = tree->root; node;) {
305 parent = node;
306 const int cmp = tree->cmp_func(key, node->key);
307 if (cmp < 0)
308 node = node->llink;
309 else if (cmp)
310 node = node->rlink;
311 else {
312 splay(tree, node);
313 ASSERT(tree->root == node);
314 return &node->datum;
315 }
316 }
317 if (parent)
318 splay(tree, parent);
319 return NULL;
320}
321
322void**
324{
325 sp_node* node = tree_search_le_node(tree, key);
326 if (node) {
327 splay(tree, node);
328 ASSERT(tree->root == node);
329 return &node->datum;
330 }
331 return NULL;
332}
333
334void**
336{
337 sp_node* node = tree_search_lt_node(tree, key);
338 if (node) {
339 splay(tree, node);
340 ASSERT(tree->root == node);
341 return &node->datum;
342 }
343 return NULL;
344}
345
346void**
348{
349 sp_node* node = tree_search_ge_node(tree, key);
350 if (node) {
351 splay(tree, node);
352 ASSERT(tree->root == node);
353 return &node->datum;
354 }
355 return NULL;
356}
357
358void**
360{
361 sp_node* node = tree_search_gt_node(tree, key);
362 if (node) {
363 splay(tree, node);
364 ASSERT(tree->root == node);
365 return &node->datum;
366 }
367 return NULL;
368}
369
370static void
371remove_node(sp_tree* tree, sp_node* node)
372{
373 sp_node* out;
374 if (!node->llink || !node->rlink) {
375 out = node;
376 } else {
377 out = tree_node_min(node->rlink);
378 void* tmp;
379 SWAP(node->key, out->key, tmp);
380 SWAP(node->datum, out->datum, tmp);
381 }
382
383 sp_node* const temp = out->llink ? out->llink : out->rlink;
384 sp_node* const parent = out->parent;
385 /* Splice before freeing: comparing a pointer to a freed object is UB. */
386 *(parent ? (parent->llink == out ? &parent->llink : &parent->rlink) : &tree->root) = temp;
387 FREE(out);
388 if (temp)
389 temp->parent = parent;
390 if (parent)
391 splay(tree, parent);
392 tree->count--;
393}
394
396sp_tree_remove(sp_tree* tree, const void* key)
397{
398 sp_node* node = tree_search_node(tree, key);
399 if (!node)
400 return (dict_remove_result) { NULL, NULL, false };
401 dict_remove_result result = { node->key, node->datum, true };
402 remove_node(tree, node);
403 return result;
404}
405
406size_t sp_tree_traverse(sp_tree* tree, dict_visit_func visit, void* user_data) { return tree_traverse(tree, visit, user_data); }
407bool sp_tree_select(sp_tree* tree, size_t n, const void** key, void** datum) { return tree_select(tree, n, key, datum); }
408size_t sp_tree_count(const sp_tree* tree) { return tree_count(tree); }
412
413static sp_node*
414node_new(void* key)
415{
416 sp_node* node = MALLOC(sizeof(*node));
417 if (node) {
418 node->key = key;
419 node->datum = NULL;
420 node->parent = NULL;
421 node->llink = NULL;
422 node->rlink = NULL;
423 }
424 return node;
425}
426
427bool
429{
430 /* A splay tree has no shape invariant of its own beyond being a valid
431 * search tree, so the shared iterative check is the whole job. It must be
432 * iterative: ascending inserts make a chain as deep as the tree is large,
433 * and recursion would overflow the stack on exactly that case. */
434 return tree_verify_common(tree);
435}
436
437sp_itor*
439{
440 sp_itor* itor = MALLOC(sizeof(*itor));
441 if (itor) {
442 itor->tree = tree;
443 itor->node = NULL;
444 }
445 return itor;
446}
447
450{
451 dict_itor* itor = MALLOC(sizeof(*itor));
452 if (itor) {
453 if (!(itor->_itor = sp_itor_new(tree))) {
454 FREE(itor);
455 return NULL;
456 }
457 itor->_vtable = &sp_tree_itor_vtable;
458 }
459 return itor;
460}
461
463bool sp_itor_valid(const sp_itor* itor) { return tree_iterator_valid(itor); }
465bool sp_itor_next(sp_itor* itor) { return tree_iterator_next(itor); }
466bool sp_itor_prev(sp_itor* itor) { return tree_iterator_prev(itor); }
467bool sp_itor_nextn(sp_itor* itor, size_t count) { return tree_iterator_nextn(itor, count); }
468bool sp_itor_prevn(sp_itor* itor, size_t count) { return tree_iterator_prevn(itor, count); }
469bool sp_itor_first(sp_itor* itor) { return tree_iterator_first(itor); }
470bool sp_itor_last(sp_itor* itor) { return tree_iterator_last(itor); }
471/* TODO: use algorithm from sp_tree_search() */
472bool sp_itor_search(sp_itor* itor, const void* key) { return tree_iterator_search(itor, key); }
473bool sp_itor_search_le(sp_itor* itor, const void* key) { return tree_iterator_search_le(itor, key); }
474bool sp_itor_search_lt(sp_itor* itor, const void* key) { return tree_iterator_search_lt(itor, key); }
475bool sp_itor_search_ge(sp_itor* itor, const void* key) { return tree_iterator_search_ge(itor, key); }
476bool sp_itor_search_gt(sp_itor* itor, const void* key) { return tree_iterator_search_gt(itor, key); }
477const void* sp_itor_key(const sp_itor* itor) { return tree_iterator_key(itor); }
478void** sp_itor_datum(sp_itor* itor) { return tree_iterator_datum(itor); }
479
480int
481sp_itor_compare(const sp_itor* i1, const sp_itor* i2)
482{
483 return tree_iterator_compare(i1, i2);
484}
485
486bool
488{
489 if (!itor->node)
490 return false;
491 remove_node(itor->tree, itor->node);
492 itor->node = NULL;
493 return true;
494}
int(* dict_compare_func)(const void *, const void *)
A pointer to a function that compares two keys.
Definition dict.h:59
void(* dict_delete_func)(void *, void *)
A pointer to a function that is called when a key-value pair gets removed from a dictionary.
Definition dict.h:62
bool(* dict_visit_func)(const void *, void *, void *)
A pointer to a function used for iterating over dictionary contents.
Definition dict.h:64
#define FREE(p)
#define ASSERT(expr)
#define MALLOC(n)
#define SWAP(a, b, v)
bool sp_itor_last(sp_itor *itor)
Position |itor| on the last element in key order and return true, or unposition it and return false i...
Definition sp_tree.c:470
dict * sp_dict_new(dict_compare_func cmp_func)
Like sp_tree_new(), but wrapped in a generic dict for use with the dict_* macros.
Definition sp_tree.c:141
dict_remove_result sp_tree_remove(sp_tree *tree, const void *key)
Remove the element with key |key|.
Definition sp_tree.c:396
void ** sp_itor_datum(sp_itor *itor)
Return the address of the datum |itor| is positioned on, through which it can be read or replaced,...
Definition sp_tree.c:478
bool sp_itor_nextn(sp_itor *itor, size_t count)
Move |itor| |count| elements forward and return whether it is still positioned.
Definition sp_tree.c:467
bool sp_itor_search_ge(sp_itor *itor, const void *key)
Position |itor| on the least key greater than or equal to |key| and return true, or unposition it and...
Definition sp_tree.c:475
bool sp_itor_prev(sp_itor *itor)
Move |itor| to the previous element in key order and return true, or unposition it and return false i...
Definition sp_tree.c:466
dict_insert_result sp_tree_insert(sp_tree *tree, void *key)
Insert |key| unless an equal key is present.
Definition sp_tree.c:260
size_t sp_tree_clear(sp_tree *tree, dict_delete_func delete_func)
Remove every element, calling |delete_func|(key, datum) for each unless |delete_func| is NULL.
Definition sp_tree.c:155
void sp_itor_free(sp_itor *itor)
Free an iterator.
Definition sp_tree.c:462
bool sp_tree_select(sp_tree *tree, size_t n, const void **key, void **datum)
Store the key and datum of the |n|th element in key order (0-based) through |key| and |datum| and ret...
Definition sp_tree.c:407
size_t sp_tree_min_path_length(const sp_tree *tree)
Return the shallowest depth at which a child link is absent, the root being at depth 1,...
Definition sp_tree.c:409
sp_itor * sp_itor_new(sp_tree *tree)
Create an iterator over |tree| that is not positioned on any element yet.
Definition sp_tree.c:438
bool sp_itor_next(sp_itor *itor)
Move |itor| to the next element in key order and return true, or unposition it and return false if th...
Definition sp_tree.c:465
int sp_itor_compare(const sp_itor *i1, const sp_itor *i2)
Compare the positions of two iterators over the same tree: return a negative value,...
Definition sp_tree.c:481
bool sp_itor_remove(sp_itor *itor)
Remove the element |itor| is positioned on and unposition |itor|; return false if it was not position...
Definition sp_tree.c:487
bool sp_itor_prevn(sp_itor *itor, size_t count)
Move |itor| |count| elements back and return whether it is still positioned.
Definition sp_tree.c:468
size_t sp_tree_max_path_length(const sp_tree *tree)
Return the greatest depth of any node, the root being at depth 1, or 0 for an empty tree: the height ...
Definition sp_tree.c:410
void ** sp_tree_search_lt(sp_tree *tree, const void *key)
Return the address of the datum of the greatest key less than |key|, or NULL if there is none.
Definition sp_tree.c:335
dict_itor * sp_dict_itor_new(sp_tree *tree)
Like sp_itor_new(), but wrapped in a generic dict_itor for use with the dict_itor_* macros.
Definition sp_tree.c:449
size_t sp_tree_free(sp_tree *tree, dict_delete_func delete_func)
Remove every element, calling |delete_func|(key, datum) for each unless |delete_func| is NULL,...
Definition sp_tree.c:154
size_t sp_tree_traverse(sp_tree *tree, dict_visit_func visit, void *user_data)
Call |visit|(key, datum, |user_data|) for each element in key order, stopping early if |visit| return...
Definition sp_tree.c:406
void sp_itor_invalidate(sp_itor *itor)
Unposition |itor|, so that it is not positioned on any element.
Definition sp_tree.c:464
size_t sp_tree_count(const sp_tree *tree)
Return the number of elements.
Definition sp_tree.c:408
void ** sp_tree_search_gt(sp_tree *tree, const void *key)
Return the address of the datum of the least key greater than |key|, or NULL if there is none.
Definition sp_tree.c:359
void ** sp_tree_search_le(sp_tree *tree, const void *key)
Return the address of the datum of the greatest key less than or equal to |key|, or NULL if there is ...
Definition sp_tree.c:323
bool sp_itor_valid(const sp_itor *itor)
Return whether |itor| is positioned on an element.
Definition sp_tree.c:463
bool sp_itor_search_le(sp_itor *itor, const void *key)
Position |itor| on the greatest key less than or equal to |key| and return true, or unposition it and...
Definition sp_tree.c:473
bool sp_tree_verify(const sp_tree *tree)
Check the internal invariants of the tree and return true if they hold, or print the first failed che...
Definition sp_tree.c:428
bool sp_itor_first(sp_itor *itor)
Position |itor| on the first element in key order and return true, or unposition it and return false ...
Definition sp_tree.c:469
size_t sp_tree_total_path_length(const sp_tree *tree)
Return the sum of the depths of all nodes, the root being at depth 1, or 0 for an empty tree.
Definition sp_tree.c:411
bool sp_itor_search_lt(sp_itor *itor, const void *key)
Position |itor| on the greatest key less than |key| and return true, or unposition it and return fals...
Definition sp_tree.c:474
const void * sp_itor_key(const sp_itor *itor)
Return the key |itor| is positioned on, or NULL if it is not positioned.
Definition sp_tree.c:477
bool sp_itor_search_gt(sp_itor *itor, const void *key)
Position |itor| on the least key greater than |key| and return true, or unposition it and return fals...
Definition sp_tree.c:476
sp_tree * sp_tree_new(dict_compare_func cmp_func)
Create an empty tree that orders keys with |cmp_func| (must not be NULL).
Definition sp_tree.c:126
void ** sp_tree_search_ge(sp_tree *tree, const void *key)
Return the address of the datum of the least key greater than or equal to |key|, or NULL if there is ...
Definition sp_tree.c:347
void ** sp_tree_search(sp_tree *tree, const void *key)
Return the address of the datum stored for |key|, or NULL if |key| is not present.
Definition sp_tree.c:301
bool sp_itor_search(sp_itor *itor, const void *key)
Position |itor| on |key| and return true, or unposition it and return false if |key| is not present.
Definition sp_tree.c:472
Splay tree.
void * _itor
Definition dict.h:235
const itor_vtable * _vtable
Definition dict.h:236
The operations of one container type.
Definition dict.h:110
Definition dict.h:164
void * _object
Definition dict.h:165
const dict_vtable * _vtable
Definition dict.h:166
sp_node * node
Definition sp_tree.c:63
sp_tree * tree
Definition sp_tree.c:63
sp_node * parent
Definition sp_tree.c:55
sp_node * llink
Definition sp_tree.c:55
void * datum
Definition sp_tree.c:55
void * key
Definition sp_tree.c:55
sp_node * rlink
Definition sp_tree.c:55
sp_node * root
Definition sp_tree.c:59
size_t rotation_count
Definition sp_tree.c:59
dict_compare_func cmp_func
Definition tree_common.c:38
tree_node * root
Definition tree_common.c:38
size_t count
Definition tree_common.c:38
size_t rotation_count
Definition tree_common.c:38
bool tree_iterator_last(void *Iterator)
size_t tree_free(void *Tree, dict_delete_func delete_func)
void * tree_search_gt_node(void *Tree, const void *key)
void ** tree_iterator_datum(void *Iterator)
bool tree_iterator_next(void *Iterator)
void * tree_search_le_node(void *Tree, const void *key)
void tree_iterator_invalidate(void *Iterator)
int tree_iterator_compare(const void *Iterator1, const void *Iterator2)
void * tree_search_node(void *Tree, const void *key)
bool tree_verify_common(const void *Tree)
bool tree_iterator_search_le(void *Iterator, const void *key)
void * tree_search_lt_node(void *Tree, const void *key)
bool tree_iterator_valid(const void *Iterator)
size_t tree_count(const void *Tree)
size_t tree_clear(void *Tree, dict_delete_func delete_func)
const void * tree_iterator_key(const void *Iterator)
size_t tree_min_path_length(const void *Tree)
void * tree_node_min(void *Node)
bool tree_iterator_nextn(void *Iterator, size_t count)
size_t tree_traverse(void *Tree, dict_visit_func visit, void *user_data)
size_t tree_total_path_length(const void *Tree)
bool tree_iterator_first(void *Iterator)
bool tree_select(void *Tree, size_t n, const void **key, void **datum)
void tree_iterator_free(void *Iterator)
bool tree_iterator_prevn(void *Iterator, size_t count)
bool tree_iterator_search_lt(void *Iterator, const void *key)
bool tree_iterator_search_ge(void *Iterator, const void *key)
size_t tree_max_path_length(const void *Tree)
void * tree_iterator_key_vt(void *Iterator)
int tree_iterator_compare_vt(void *Iterator1, void *Iterator2)
bool tree_iterator_search_gt(void *Iterator, const void *key)
void * tree_search_ge_node(void *Tree, const void *key)
bool tree_iterator_search(void *Iterator, const void *key)
bool tree_iterator_prev(void *Iterator)
#define TREE_NODE_FIELDS(node_type)
Definition tree_common.h:33
#define TREE_ITERATOR_FIELDS(tree_type, node_type)
Definition tree_common.h:54
#define TREE_FIELDS(node_type)
Definition tree_common.h:44