libdict 1.0.7
Data Structure C Library
Loading...
Searching...
No Matches
wb_tree.c
Go to the documentation of this file.
1/*
2 * libdict -- weight-balanced 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. [Gonnet 1984], [Nievergelt and Reingold 1973]
30 */
31
32#include "wb_tree.h"
33
34#include <stdint.h>
35#include "dict_private.h"
36#include "tree_common.h"
37
38/* A tree BB[alpha] is said to be of weighted balance alpha if every node in
39 * the tree has a balance p(n) such that alpha <= p(n) <= 1 - alpha. The
40 * balance of a node is defined as the number of nodes in its left subtree
41 * divided by the number of nodes in the subtree rooted at that node. The
42 * weight of a node is defined as the number of external nodes in its
43 * subtrees.
44 *
45 * Legal values for alpha are 0 <= alpha <= 1/2. BB[0] is a normal, unbalanced
46 * binary tree, and BB[1/2] includes only completely balanced binary search
47 * trees of 2^height - 1 nodes. A higher value of alpha specifies a more
48 * stringent balance requirement.
49 *
50 * Values for alpha in the range 2/11 <= alpha <= 1 - sqrt(2)/2 are interesting
51 * because a tree can be brought back into weighted balance after an insertion or
52 * deletion using at most one rotation per level (thus the number of rotations
53 * after insertion or deletion is O(lg N)).
54 *
55 * These are the parameters for alpha = 1 - sqrt(2)/2 == .292893, as
56 * recommended in [Gonnet 1984]. */
57
58/* These constants are approximated by integer fractions in the code to
59 * eliminate floating point arithmetic. */
60#if 0
61# define ALPHA_0 .292893f /* 1 - sqrt(2)/2 */
62# define ALPHA_1 .707106f /* sqrt(2)/2 */
63# define ALPHA_2 .414213f /* sqrt(2) - 1 */
64# define ALPHA_3 .585786f /* 2 - sqrt(2) */
65#endif
66
67typedef struct wb_node wb_node;
68struct wb_node {
70 uint32_t weight;
71};
72
73#define WEIGHT(n) ((n) ? (n)->weight : 1U)
74
78
82
83/* Vtable thunks. The vtable slot types take void*, and calling a function
84 * through a function-pointer type that is not compatible with the function's
85 * own type is undefined behaviour (C11 6.5.2.2p9), so each slot below gets a
86 * thunk with the exact slot signature instead of a cast. A cast would also
87 * hide a genuine signature mismatch. */
88static dict_itor* vt_wb_dict_itor_new(void* obj) { return wb_dict_itor_new(obj); }
89static dict_insert_result vt_wb_tree_insert(void* obj, void* key) { return wb_tree_insert(obj, key); }
90static dict_remove_result vt_wb_tree_remove(void* obj, const void* key) { return wb_tree_remove(obj, key); }
91static bool vt_wb_tree_select(void* obj, size_t n, const void** key, void** datum) { return wb_tree_select(obj, n, key, datum); }
92static bool vt_wb_tree_verify(const void* obj) { return wb_tree_verify(obj); }
93static bool vt_wb_itor_remove(void* itor) { return wb_itor_remove(itor); }
94
95static const dict_vtable wb_tree_vtable = {
96 true,
97 vt_wb_dict_itor_new,
99 vt_wb_tree_insert,
105 vt_wb_tree_remove,
108 vt_wb_tree_select,
110 vt_wb_tree_verify,
111};
112
113static const itor_vtable wb_tree_itor_vtable = {
130 vt_wb_itor_remove,
132};
133
134static wb_node* node_new(void* key);
135
136wb_tree*
138{
139 ASSERT(cmp_func != NULL);
140
141 wb_tree* tree = MALLOC(sizeof(*tree));
142 if (tree) {
143 tree->root = NULL;
144 tree->count = 0;
145 tree->cmp_func = cmp_func;
146 tree->rotation_count = 0;
147 }
148 return tree;
149}
150
151dict*
153{
154 dict* dct = MALLOC(sizeof(*dct));
155 if (dct) {
156 if (!(dct->_object = wb_tree_new(cmp_func))) {
157 FREE(dct);
158 return NULL;
159 }
160 dct->_vtable = &wb_tree_vtable;
161 }
162 return dct;
163}
164
165void** wb_tree_search(wb_tree* tree, const void* key) { return tree_search(tree, key); }
166void** wb_tree_search_le(wb_tree* tree, const void* key) { return tree_search_le(tree, key); }
167void** wb_tree_search_lt(wb_tree* tree, const void* key) { return tree_search_lt(tree, key); }
168void** wb_tree_search_ge(wb_tree* tree, const void* key) { return tree_search_ge(tree, key); }
169void** wb_tree_search_gt(wb_tree* tree, const void* key) { return tree_search_gt(tree, key); }
170
171static inline unsigned
172fixup(wb_tree* tree, wb_node* n)
173{
174 unsigned rotations = 0;
175 unsigned weight = WEIGHT(n->llink);
176 if ((uint64_t) weight * 1000U < (uint64_t) n->weight * 293U) {
177 wb_node* nr = n->rlink;
178 ASSERT(nr != NULL);
179 wb_node* nrl = nr->llink;
180 if ((uint64_t) WEIGHT(nrl) * 1000U < (uint64_t) nr->weight * 586U) { /* RR */
181 /* Rotate |n| left. */
183 nr->weight = (n->weight = WEIGHT(n->llink) + WEIGHT(n->rlink)) +
184 WEIGHT(nr->rlink);
185 rotations += 1;
186 } else { /* RL */
187 /* Rotate |nr| right, then |n| left. */
188 ASSERT(nrl != NULL);
189 wb_node* const p = n->parent;
190 nrl->parent = p;
191 *(p ? (p->llink == n ? &p->llink : &p->rlink) : &tree->root) = nrl;
192
193 wb_node* const a = nrl->llink;
194 nrl->llink = n;
195 n->parent = nrl;
196 if ((n->rlink = a) != NULL)
197 a->parent = n;
198
199 wb_node* const b = nrl->rlink;
200 nrl->rlink = nr;
201 nr->parent = nrl;
202 if ((nr->llink = b) != NULL)
203 b->parent = nr;
204
205 nrl->weight = (n->weight = WEIGHT(n->llink) + WEIGHT(a)) +
206 (nr->weight = WEIGHT(b) + WEIGHT(nr->rlink));
207 rotations += 2;
208 }
209 } else if ((uint64_t) weight * 1000U > (uint64_t) n->weight * 707U) {
210 wb_node* nl = n->llink;
211 ASSERT(nl != NULL);
212 weight = WEIGHT(nl->llink);
213 if ((uint64_t) weight * 1000U > (uint64_t) nl->weight * 414U) { /* LL */
215
216 n->weight = WEIGHT(n->llink) + WEIGHT(n->rlink);
217 nl->weight = weight + n->weight;
218 rotations += 1;
219 } else { /* LR */
220 /* Rotate |nl| left, then |n| right. */
221 wb_node* nlr = nl->rlink;
222 ASSERT(nlr != NULL);
223 wb_node* const p = n->parent;
224 nlr->parent = p;
225 *(p ? (p->llink == n ? &p->llink : &p->rlink) : &tree->root) = nlr;
226
227 wb_node* const a = nlr->llink;
228 nlr->llink = nl;
229 nl->parent = nlr;
230 if ((nl->rlink = a) != NULL)
231 a->parent = nl;
232
233 wb_node* const b = nlr->rlink;
234 nlr->rlink = n;
235 n->parent = nlr;
236 if ((n->llink = b) != NULL)
237 b->parent = n;
238
239 nlr->weight = (n->weight = WEIGHT(b) + WEIGHT(n->rlink)) +
240 (nl->weight = WEIGHT(nl->llink) + WEIGHT(a));
241 rotations += 2;
242 }
243 }
244 return rotations;
245}
246
249{
250 int cmp = 0;
251
252 wb_node* node = tree->root;
253 wb_node* parent = NULL;
254 while (node) {
255 cmp = tree->cmp_func(key, node->key);
256 if (cmp < 0) {
257 parent = node; node = node->llink;
258 } else if (cmp) {
259 parent = node; node = node->rlink;
260 } else
261 return (dict_insert_result) { &node->datum, false };
262 }
263
264 wb_node* const add = node = node_new(key);
265 if (!add)
266 return (dict_insert_result) { NULL, false };
267
268 if (!(node->parent = parent)) {
269 ASSERT(tree->count == 0);
270 ASSERT(tree->root == NULL);
271 tree->root = node;
272 } else {
273 if (cmp < 0)
274 parent->llink = node;
275 else
276 parent->rlink = node;
277
278 unsigned rotations = 0;
279 while ((node = parent) != NULL) {
280 parent = node->parent;
281 ++node->weight;
282 rotations += fixup(tree, node);
283 }
284 tree->rotation_count += rotations;
285 }
286 tree->count++;
287 return (dict_insert_result) { &add->datum, true };
288}
289
290static void
291remove_node(wb_tree* tree, wb_node* node)
292{
293 if (node->llink && node->rlink) {
294 wb_node* out;
295 if (node->llink->weight > node->rlink->weight) {
296 out = tree_node_max(node->llink);
297 } else {
298 out = tree_node_min(node->rlink);
299 }
300 void* tmp;
301 SWAP(node->key, out->key, tmp);
302 SWAP(node->datum, out->datum, tmp);
303 node = out;
304 }
305 ASSERT(!node->llink || !node->rlink);
306 /* Splice in the node's only child, if any. */
307 wb_node* child = node->llink ? node->llink : node->rlink;
308 wb_node* parent = node->parent;
309 if (child)
310 child->parent = parent;
311 *(parent ? (parent->llink == node ? &parent->llink : &parent->rlink) : &tree->root) = child;
312 FREE(node);
313 tree->count--;
314 /* Now move up the tree, decrementing weights. */
315 unsigned rotations = 0;
316 while (parent) {
317 --parent->weight;
318 wb_node* up = parent->parent;
319 rotations += fixup(tree, parent);
320 parent = up;
321 }
322 tree->rotation_count += rotations;
323}
324
326wb_tree_remove(wb_tree* tree, const void* key)
327{
328 wb_node* node = tree_search_node(tree, key);
329 if (!node)
330 return (dict_remove_result) { NULL, NULL, false };
331 dict_remove_result result = { node->key, node->datum, true };
332 remove_node(tree, node);
333 return result;
334}
335
336size_t wb_tree_free(wb_tree* tree, dict_delete_func delete_func) { return tree_free(tree, delete_func); }
337size_t wb_tree_clear(wb_tree* tree, dict_delete_func delete_func) { return tree_clear(tree, delete_func); }
338size_t wb_tree_traverse(wb_tree* tree, dict_visit_func visit, void* user_data) { return tree_traverse(tree, visit, user_data); }
339
340bool
341wb_tree_select(wb_tree* tree, size_t n, const void** key, void** datum)
342{
343 if (n >= tree->count) {
344 if (key)
345 *key = NULL;
346 if (datum)
347 *datum = NULL;
348 return false;
349 }
350 wb_node* node = tree->root;
351 for (;;) {
352 const unsigned nw = WEIGHT(node->llink);
353 if (n + 1 >= nw) {
354 if (n + 1 == nw) {
355 if (key)
356 *key = node->key;
357 if (datum)
358 *datum = node->datum;
359 return true;
360 }
361 n -= nw;
362 node = node->rlink;
363 } else {
364 node = node->llink;
365 }
366 }
367}
368
369size_t wb_tree_count(const wb_tree* tree) { return tree_count(tree); }
373
374static wb_node*
375node_new(void* key)
376{
377 wb_node* node = MALLOC(sizeof(*node));
378 if (node) {
379 node->key = key;
380 node->datum = NULL;
381 node->parent = NULL;
382 node->llink = NULL;
383 node->rlink = NULL;
384 node->weight = 2;
385 }
386 return node;
387}
388
389static bool
390node_verify(const wb_tree* tree, const wb_node* parent, const wb_node* node,
391 unsigned *weight, const void* lower, const void* upper)
392{
393 if (!parent) {
394 VERIFY(tree->root == node);
395 } else {
396 VERIFY(parent->llink == node || parent->rlink == node);
397 }
398 if (node) {
399 VERIFY(node->parent == parent);
400 /* Global BST ordering. Comparing a node only against its immediate
401 * parent would accept an entire subtree placed on the wrong side:
402 * root 5, 5->llink 3, 3->rlink 7 passes every parent-local check yet
403 * makes key 7 unreachable from the root. */
404 if (lower)
405 VERIFY(tree->cmp_func(lower, node->key) < 0);
406 if (upper)
407 VERIFY(tree->cmp_func(upper, node->key) > 0);
408 unsigned lweight, rweight;
409 if (!node_verify(tree, node, node->llink, &lweight, lower, node->key) ||
410 !node_verify(tree, node, node->rlink, &rweight, node->key, upper))
411 return false;
412 VERIFY(WEIGHT(node->llink) == lweight);
413 VERIFY(WEIGHT(node->rlink) == rweight);
414 VERIFY(node->weight == lweight + rweight);
415 VERIFY((uint64_t) lweight * 1000U >= (uint64_t) node->weight * 292U);
416 VERIFY((uint64_t) lweight * 1000U <= (uint64_t) node->weight * 708U);
417 *weight = lweight + rweight;
418 } else {
419 *weight = 1;
420 }
421 return true;
422}
423
424bool
426{
427 if (tree->root) {
428 VERIFY(tree->count > 0);
429 VERIFY(tree->count + 1 == tree->root->weight);
430 } else {
431 VERIFY(tree->count == 0);
432 }
433 /* The weight relationships are checked inside node_verify(); the
434 * top-level weight itself is already covered by the count check above. */
435 unsigned root_weight;
436 return node_verify(tree, NULL, tree->root, &root_weight, NULL, NULL);
437}
438
439wb_itor*
441{
442 wb_itor* itor = MALLOC(sizeof(*itor));
443 if (itor) {
444 itor->tree = tree;
445 itor->node = NULL;
446 }
447 return itor;
448}
449
452{
453 dict_itor* itor = MALLOC(sizeof(*itor));
454 if (itor) {
455 if (!(itor->_itor = wb_itor_new(tree))) {
456 FREE(itor);
457 return NULL;
458 }
459 itor->_vtable = &wb_tree_itor_vtable;
460 }
461 return itor;
462}
463
465bool wb_itor_valid(const wb_itor* itor) { return tree_iterator_valid(itor); }
467bool wb_itor_next(wb_itor* itor) { return tree_iterator_next(itor); }
468bool wb_itor_prev(wb_itor* itor) { return tree_iterator_prev(itor); }
469bool wb_itor_nextn(wb_itor* itor, size_t count) { return tree_iterator_nextn(itor, count); } /* TODO: speed up */
470bool wb_itor_prevn(wb_itor* itor, size_t count) { return tree_iterator_prevn(itor, count); } /* TODO: speed up */
471bool wb_itor_first(wb_itor* itor) { return tree_iterator_first(itor); }
472bool wb_itor_last(wb_itor* itor) { return tree_iterator_last(itor); }
473bool wb_itor_search(wb_itor* itor, const void* key) { return tree_iterator_search(itor, key); }
474bool wb_itor_search_le(wb_itor* itor, const void* key) { return tree_iterator_search_le(itor, key); }
475bool wb_itor_search_lt(wb_itor* itor, const void* key) { return tree_iterator_search_lt(itor, key); }
476bool wb_itor_search_ge(wb_itor* itor, const void* key) { return tree_iterator_search_ge(itor, key); }
477bool wb_itor_search_gt(wb_itor* itor, const void* key) { return tree_iterator_search_gt(itor, key); }
478const void* wb_itor_key(const wb_itor* itor) { return tree_iterator_key(itor); }
479void** wb_itor_datum(wb_itor* itor) { return tree_iterator_datum(itor); }
480int wb_itor_compare(const wb_itor* i1, const wb_itor* i2) { return tree_iterator_compare(i1, i2); }
481
482bool
484{
485 if (!itor->node)
486 return false;
487 remove_node(itor->tree, itor->node);
488 itor->node = NULL;
489 return true;
490}
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 VERIFY(expr)
#define MALLOC(n)
#define SWAP(a, b, v)
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
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
wb_node * node
Definition wb_tree.c:80
wb_tree * tree
Definition wb_tree.c:80
wb_node * parent
Definition wb_tree.c:69
void * datum
Definition wb_tree.c:69
uint32_t weight
Definition wb_tree.c:70
void * key
Definition wb_tree.c:69
wb_node * rlink
Definition wb_tree.c:69
wb_node * llink
Definition wb_tree.c:69
bool tree_iterator_last(void *Iterator)
size_t tree_free(void *Tree, dict_delete_func delete_func)
void ** tree_iterator_datum(void *Iterator)
bool tree_iterator_next(void *Iterator)
void * tree_node_max(void *Node)
void tree_iterator_invalidate(void *Iterator)
void ** tree_search_gt(void *Tree, const void *key)
int tree_iterator_compare(const void *Iterator1, const void *Iterator2)
void tree_node_rot_left(void *Tree, void *Node)
Definition tree_common.c:46
void * tree_search_node(void *Tree, const void *key)
bool tree_iterator_search_le(void *Iterator, const void *key)
bool tree_iterator_valid(const void *Iterator)
size_t tree_count(const void *Tree)
void ** tree_search_lt(void *Tree, const void *key)
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)
void ** tree_search(void *Tree, const void *key)
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)
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(void *Tree, const void *key)
void tree_node_rot_right(void *Tree, void *Node)
Definition tree_common.c:62
void ** tree_search_le(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
bool wb_itor_first(wb_itor *itor)
Position |itor| on the first element in key order and return true, or unposition it and return false ...
Definition wb_tree.c:471
size_t wb_tree_clear(wb_tree *tree, dict_delete_func delete_func)
Remove every element, calling |delete_func|(key, datum) for each unless |delete_func| is NULL.
Definition wb_tree.c:337
void wb_itor_free(wb_itor *itor)
Free an iterator.
Definition wb_tree.c:464
void ** wb_tree_search_ge(wb_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 wb_tree.c:168
void ** wb_tree_search_le(wb_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 wb_tree.c:166
size_t wb_tree_count(const wb_tree *tree)
Return the number of elements.
Definition wb_tree.c:369
int wb_itor_compare(const wb_itor *i1, const wb_itor *i2)
Compare the positions of two iterators over the same tree: return a negative value,...
Definition wb_tree.c:480
bool wb_itor_last(wb_itor *itor)
Position |itor| on the last element in key order and return true, or unposition it and return false i...
Definition wb_tree.c:472
bool wb_itor_search_lt(wb_itor *itor, const void *key)
Position |itor| on the greatest key less than |key| and return true, or unposition it and return fals...
Definition wb_tree.c:475
const void * wb_itor_key(const wb_itor *itor)
Return the key |itor| is positioned on, or NULL if it is not positioned.
Definition wb_tree.c:478
bool wb_itor_remove(wb_itor *itor)
Remove the element |itor| is positioned on and unposition |itor|; return false if it was not position...
Definition wb_tree.c:483
bool wb_itor_search_gt(wb_itor *itor, const void *key)
Position |itor| on the least key greater than |key| and return true, or unposition it and return fals...
Definition wb_tree.c:477
void ** wb_tree_search_lt(wb_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 wb_tree.c:167
size_t wb_tree_traverse(wb_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 wb_tree.c:338
wb_tree * wb_tree_new(dict_compare_func cmp_func)
Create an empty tree that orders keys with |cmp_func| (must not be NULL).
Definition wb_tree.c:137
dict_insert_result wb_tree_insert(wb_tree *tree, void *key)
Insert |key| unless an equal key is present.
Definition wb_tree.c:248
dict * wb_dict_new(dict_compare_func cmp_func)
Like wb_tree_new(), but wrapped in a generic dict for use with the dict_* macros.
Definition wb_tree.c:152
bool wb_itor_prevn(wb_itor *itor, size_t count)
Move |itor| |count| elements back and return whether it is still positioned.
Definition wb_tree.c:470
dict_itor * wb_dict_itor_new(wb_tree *tree)
Like wb_itor_new(), but wrapped in a generic dict_itor for use with the dict_itor_* macros.
Definition wb_tree.c:451
bool wb_itor_search(wb_itor *itor, const void *key)
Position |itor| on |key| and return true, or unposition it and return false if |key| is not present.
Definition wb_tree.c:473
bool wb_tree_verify(const wb_tree *tree)
Check the internal invariants of the tree and return true if they hold, or print the first failed che...
Definition wb_tree.c:425
void ** wb_itor_datum(wb_itor *itor)
Return the address of the datum |itor| is positioned on, through which it can be read or replaced,...
Definition wb_tree.c:479
bool wb_itor_search_ge(wb_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 wb_tree.c:476
bool wb_itor_nextn(wb_itor *itor, size_t count)
Move |itor| |count| elements forward and return whether it is still positioned.
Definition wb_tree.c:469
bool wb_itor_search_le(wb_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 wb_tree.c:474
void wb_itor_invalidate(wb_itor *itor)
Unposition |itor|, so that it is not positioned on any element.
Definition wb_tree.c:466
size_t wb_tree_free(wb_tree *tree, dict_delete_func delete_func)
Remove every element, calling |delete_func|(key, datum) for each unless |delete_func| is NULL,...
Definition wb_tree.c:336
#define WEIGHT(n)
Definition wb_tree.c:73
bool wb_itor_valid(const wb_itor *itor)
Return whether |itor| is positioned on an element.
Definition wb_tree.c:465
bool wb_itor_prev(wb_itor *itor)
Move |itor| to the previous element in key order and return true, or unposition it and return false i...
Definition wb_tree.c:468
bool wb_tree_select(wb_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 wb_tree.c:341
size_t wb_tree_min_path_length(const wb_tree *tree)
Return the shallowest depth at which a child link is absent, the root being at depth 1,...
Definition wb_tree.c:370
dict_remove_result wb_tree_remove(wb_tree *tree, const void *key)
Remove the element with key |key|.
Definition wb_tree.c:326
bool wb_itor_next(wb_itor *itor)
Move |itor| to the next element in key order and return true, or unposition it and return false if th...
Definition wb_tree.c:467
void ** wb_tree_search(wb_tree *tree, const void *key)
Return the address of the datum stored for |key|, or NULL if |key| is not present.
Definition wb_tree.c:165
void ** wb_tree_search_gt(wb_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 wb_tree.c:169
wb_itor * wb_itor_new(wb_tree *tree)
Create an iterator over |tree| that is not positioned on any element yet.
Definition wb_tree.c:440
size_t wb_tree_max_path_length(const wb_tree *tree)
Return the greatest depth of any node, the root being at depth 1, or 0 for an empty tree: the height ...
Definition wb_tree.c:371
size_t wb_tree_total_path_length(const wb_tree *tree)
Return the sum of the depths of all nodes, the root being at depth 1, or 0 for an empty tree.
Definition wb_tree.c:372
Weight-balanced tree, BB[alpha] with alpha = 1 - sqrt(2)/2.