libdict 1.0.7
Data Structure C Library
Loading...
Searching...
No Matches
rb_tree.c
Go to the documentation of this file.
1/*
2 * libdict -- red-black 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. [Cormen, Leiserson, and Rivest 1990], [Guibas and Sedgewick, 1978]
30 */
31
32#include "rb_tree.h"
33
34#include "dict_private.h"
35#include "tree_common.h"
36
37typedef struct rb_node rb_node;
38struct rb_node {
39 void* key;
40 void* datum;
41 intptr_t color;
44};
45
46#define RB_RED 0
47#define RB_BLACK 1
48
49#define PARENT(node) ((rb_node*)((node)->color & ~RB_BLACK))
50#define COLOR(node) ((node)->color & RB_BLACK)
51
52#define SET_RED(node) (node)->color &= (~(intptr_t)RB_BLACK)
53#define SET_BLACK(node) (node)->color |= ((intptr_t)RB_BLACK)
54#define SET_PARENT(node,p) (node)->color = COLOR(node) | (intptr_t)(p)
55
56/* rb_node is handed to the generic routines in tree_common.c as though it were
57 * a tree_node_base, so its first five members must sit at the same offsets.
58 * The third of those, the parent pointer, additionally carries the colour in
59 * its low bit, so ONLY this file's PARENT() macro may decode it: any
60 * tree_common routine that reads |parent| directly (tree_traverse,
61 * tree_select, tree_clear, tree_iterator_next/prev, tree_node_rot_*) would
62 * dereference a tagged pointer and must be reimplemented here. */
63_Static_assert(sizeof(intptr_t) == sizeof(rb_node*),
64 "rb_node tags a parent pointer stored in an intptr_t");
65_Static_assert(offsetof(rb_node, key) == offsetof(tree_node_base, key),
66 "rb_node must be layout-compatible with tree_node_base");
67_Static_assert(offsetof(rb_node, datum) == offsetof(tree_node_base, datum),
68 "rb_node must be layout-compatible with tree_node_base");
69_Static_assert(offsetof(rb_node, color) == offsetof(tree_node_base, parent),
70 "rb_node must be layout-compatible with tree_node_base");
71_Static_assert(offsetof(rb_node, llink) == offsetof(tree_node_base, llink),
72 "rb_node must be layout-compatible with tree_node_base");
73_Static_assert(offsetof(rb_node, rlink) == offsetof(tree_node_base, rlink),
74 "rb_node must be layout-compatible with tree_node_base");
75
79
83
84/* Vtable thunks. The vtable slot types take void*, and calling a function
85 * through a function-pointer type that is not compatible with the function's
86 * own type is undefined behaviour (C11 6.5.2.2p9), so each slot below gets a
87 * thunk with the exact slot signature instead of a cast. A cast would also
88 * hide a genuine signature mismatch. */
89static dict_itor* vt_rb_dict_itor_new(void* obj) { return rb_dict_itor_new(obj); }
90static size_t vt_rb_tree_free(void* obj, dict_delete_func delete_func) { return rb_tree_free(obj, delete_func); }
91static dict_insert_result vt_rb_tree_insert(void* obj, void* key) { return rb_tree_insert(obj, key); }
92static dict_remove_result vt_rb_tree_remove(void* obj, const void* key) { return rb_tree_remove(obj, key); }
93static size_t vt_rb_tree_clear(void* obj, dict_delete_func delete_func) { return rb_tree_clear(obj, delete_func); }
94static size_t vt_rb_tree_traverse(void* obj, dict_visit_func visit, void* user_data) { return rb_tree_traverse(obj, visit, user_data); }
95static bool vt_rb_tree_select(void* obj, size_t n, const void** key, void** datum) { return rb_tree_select(obj, n, key, datum); }
96static bool vt_rb_tree_verify(const void* obj) { return rb_tree_verify(obj); }
97static void vt_rb_itor_free(void* itor) { rb_itor_free(itor); }
98static bool vt_rb_itor_valid(const void* itor) { return rb_itor_valid(itor); }
99static void vt_rb_itor_invalidate(void* itor) { rb_itor_invalidate(itor); }
100static bool vt_rb_itor_next(void* itor) { return rb_itor_next(itor); }
101static bool vt_rb_itor_prev(void* itor) { return rb_itor_prev(itor); }
102static bool vt_rb_itor_nextn(void* itor, size_t count) { return rb_itor_nextn(itor, count); }
103static bool vt_rb_itor_prevn(void* itor, size_t count) { return rb_itor_prevn(itor, count); }
104static bool vt_rb_itor_first(void* itor) { return rb_itor_first(itor); }
105static bool vt_rb_itor_last(void* itor) { return rb_itor_last(itor); }
106static void* vt_rb_itor_key(void* itor) { return dict_unconst(rb_itor_key(itor)); }
107static void** vt_rb_itor_datum(void* itor) { return rb_itor_datum(itor); }
108static bool vt_rb_itor_search(void* itor, const void* key) { return rb_itor_search(itor, key); }
109static bool vt_rb_itor_search_le(void* itor, const void* key) { return rb_itor_search_le(itor, key); }
110static bool vt_rb_itor_search_lt(void* itor, const void* key) { return rb_itor_search_lt(itor, key); }
111static bool vt_rb_itor_search_ge(void* itor, const void* key) { return rb_itor_search_ge(itor, key); }
112static bool vt_rb_itor_search_gt(void* itor, const void* key) { return rb_itor_search_gt(itor, key); }
113static bool vt_rb_itor_remove(void* itor) { return rb_itor_remove(itor); }
114
115static const dict_vtable rb_tree_vtable = {
116 true,
117 vt_rb_dict_itor_new,
118 vt_rb_tree_free,
119 vt_rb_tree_insert,
125 vt_rb_tree_remove,
126 vt_rb_tree_clear,
127 vt_rb_tree_traverse,
128 vt_rb_tree_select,
130 vt_rb_tree_verify,
131};
132
133static const itor_vtable rb_tree_itor_vtable = {
134 vt_rb_itor_free,
135 vt_rb_itor_valid,
136 vt_rb_itor_invalidate,
137 vt_rb_itor_next,
138 vt_rb_itor_prev,
139 vt_rb_itor_nextn,
140 vt_rb_itor_prevn,
141 vt_rb_itor_first,
142 vt_rb_itor_last,
143 vt_rb_itor_key,
144 vt_rb_itor_datum,
145 vt_rb_itor_search,
146 vt_rb_itor_search_le,
147 vt_rb_itor_search_lt,
148 vt_rb_itor_search_ge,
149 vt_rb_itor_search_gt,
150 vt_rb_itor_remove,
152};
153
154static void rot_left(rb_tree* tree, rb_node* node);
155static void rot_right(rb_tree* tree, rb_node* node);
156static unsigned insert_fixup(rb_tree* tree, rb_node* node);
157static unsigned delete_fixup(rb_tree* tree, rb_node* node, rb_node* parent, bool left);
158static rb_node* node_new(void* key);
159static rb_node* node_next(rb_node* node);
160static rb_node* node_prev(rb_node* node);
161
162rb_tree*
164{
165 ASSERT(cmp_func != NULL);
166
167 rb_tree* tree = MALLOC(sizeof(*tree));
168 if (tree) {
169 tree->root = NULL;
170 tree->count = 0;
171 tree->cmp_func = cmp_func;
172 tree->rotation_count = 0;
173 }
174 return tree;
175}
176
177dict*
179{
180 dict* dct = MALLOC(sizeof(*dct));
181 if (dct) {
182 if (!(dct->_object = rb_tree_new(cmp_func))) {
183 FREE(dct);
184 return NULL;
185 }
186 dct->_vtable = &rb_tree_vtable;
187 }
188 return dct;
189}
190
191size_t
193 const size_t count = rb_tree_clear(tree, delete_func);
194 FREE(tree);
195 return count;
196}
197
198size_t
200{
201 const size_t count = tree->count;
202
203 rb_node* node = tree->root;
204 while (node) {
205 if (node->llink || node->rlink) {
206 node = node->llink ? node->llink : node->rlink;
207 continue;
208 }
209 if (delete_func) delete_func(node->key, node->datum);
210 rb_node* const parent = PARENT(node);
211 /* Unlink before freeing: comparing a pointer to a freed object is UB. */
212 *(parent ? (parent->llink == node ? &parent->llink : &parent->rlink) : &tree->root) = NULL;
213 FREE(node);
214 node = parent;
215 }
216 ASSERT(tree->root == NULL);
217 tree->count = 0;
218 tree->rotation_count = 0;
219 return count;
220}
221
222void** rb_tree_search(rb_tree* tree, const void* key) { return tree_search(tree, key); }
223void** rb_tree_search_le(rb_tree* tree, const void* key) { return tree_search_le(tree, key); }
224void** rb_tree_search_lt(rb_tree* tree, const void* key) { return tree_search_lt(tree, key); }
225void** rb_tree_search_ge(rb_tree* tree, const void* key) { return tree_search_ge(tree, key); }
226void** rb_tree_search_gt(rb_tree* tree, const void* key) { return tree_search_gt(tree, key); }
227
230{
231 int cmp = 0; /* Quell GCC warning about uninitialized usage. */
232 rb_node* node = tree->root;
233 rb_node* parent = NULL;
234 while (node) {
235 cmp = tree->cmp_func(key, node->key);
236 if (cmp < 0) {
237 parent = node; node = node->llink;
238 } else if (cmp > 0) {
239 parent = node; node = node->rlink;
240 } else
241 return (dict_insert_result) { &node->datum, false };
242 }
243
244 if (!(node = node_new(key)))
245 return (dict_insert_result) { NULL, false };
246
247 SET_PARENT(node, parent);
248 if (parent == NULL) {
249 ASSERT(tree->root == NULL);
250 tree->root = node;
251 ASSERT(tree->count == 0);
252 SET_BLACK(node);
253 } else {
254 if (cmp < 0)
255 parent->llink = node;
256 else
257 parent->rlink = node;
258
259 tree->rotation_count += insert_fixup(tree, node);
260 }
261 tree->count++;
262 return (dict_insert_result) { &node->datum, true };
263}
264
265static unsigned
266insert_fixup(rb_tree* tree, rb_node* node)
267{
268 unsigned rotations = 0;
269 while (node != tree->root && COLOR(PARENT(node)) == RB_RED) {
270 if (PARENT(node) == PARENT(PARENT(node))->llink) {
271 rb_node* temp = PARENT(PARENT(node))->rlink;
272 if (temp && COLOR(temp) == RB_RED) {
273 SET_BLACK(temp);
274 node = PARENT(node);
275 SET_BLACK(node);
276 node = PARENT(node);
277 SET_RED(node);
278 } else {
279 if (node == PARENT(node)->rlink) {
280 node = PARENT(node);
281 rot_left(tree, node);
282 ++rotations;
283 }
284 temp = PARENT(node);
285 SET_BLACK(temp);
286 temp = PARENT(temp);
287 SET_RED(temp);
288 rot_right(tree, temp);
289 ++rotations;
290 }
291 } else {
292 rb_node* temp = PARENT(PARENT(node))->llink;
293 if (temp && COLOR(temp) == RB_RED) {
294 SET_BLACK(temp);
295 node = PARENT(node);
296 SET_BLACK(node);
297 node = PARENT(node);
298 SET_RED(node);
299 } else {
300 if (node == PARENT(node)->llink) {
301 node = PARENT(node);
302 rot_right(tree, node);
303 ++rotations;
304 }
305 temp = PARENT(node);
306 SET_BLACK(temp);
307 temp = PARENT(temp);
308 SET_RED(temp);
309 rot_left(tree, temp);
310 ++rotations;
311 }
312 }
313 }
314
316 return rotations;
317}
318
319static void
320remove_node(rb_tree* tree, rb_node* node)
321{
322 rb_node* out;
323 if (!node->llink || !node->rlink) {
324 out = node;
325 } else {
326 out = tree_node_min(node->rlink);
327 void *tmp;
328 SWAP(node->key, out->key, tmp);
329 SWAP(node->datum, out->datum, tmp);
330 }
331
332 rb_node* const x = out->llink ? out->llink : out->rlink;
333 rb_node* const xp = PARENT(out);
334 if (x)
335 SET_PARENT(x, xp);
336 bool left = xp && xp->llink == out;
337 *(xp ? (xp->llink == out ? &xp->llink : &xp->rlink) : &tree->root) = x;
338
339 if (COLOR(out) == RB_BLACK && tree->root)
340 tree->rotation_count += delete_fixup(tree, x, xp, left);
341 FREE(out);
342 tree->count--;
343}
344
346rb_tree_remove(rb_tree* tree, const void* key)
347{
348 rb_node* node = tree_search_node(tree, key);
349 if (!node)
350 return (dict_remove_result) { NULL, NULL, false };
351 dict_remove_result result = { node->key, node->datum, true };
352 remove_node(tree, node);
353 return result;
354}
355
356static unsigned
357delete_fixup(rb_tree* tree, rb_node* node, rb_node* parent, bool left)
358{
359 unsigned rotations = 0;
360 while (node != tree->root && (node == NULL || COLOR(node) == RB_BLACK)) {
361 if (left) {
362 rb_node* w = parent->rlink;
363 if (COLOR(w) == RB_RED) {
364 SET_BLACK(w);
365 SET_RED(parent);
366 rot_left(tree, parent); ++rotations;
367 w = parent->rlink;
368 }
369 if ((w->llink == NULL || COLOR(w->llink) == RB_BLACK) &&
370 (w->rlink == NULL || COLOR(w->rlink) == RB_BLACK)) {
371 SET_RED(w);
372 node = parent;
373 parent = PARENT(parent);
374 left = parent && parent->llink == node;
375 } else {
376 if (w->rlink == NULL || COLOR(w->rlink) == RB_BLACK) {
377 SET_BLACK(w->llink);
378 SET_RED(w);
379 rot_right(tree, w); ++rotations;
380 w = parent->rlink;
381 }
382 if (COLOR(parent) == RB_RED)
383 SET_RED(w);
384 else
385 SET_BLACK(w);
386 if (w->rlink)
387 SET_BLACK(w->rlink);
388 SET_BLACK(parent);
389 rot_left(tree, parent); ++rotations;
390 break;
391 }
392 } else { // left == false
393 rb_node* w = parent->llink;
394 if (COLOR(w) == RB_RED) {
395 SET_BLACK(w);
396 SET_RED(parent);
397 rot_right(tree, parent); ++rotations;
398 w = parent->llink;
399 }
400 if ((w->llink == NULL || COLOR(w->llink) == RB_BLACK) &&
401 (w->rlink == NULL || COLOR(w->rlink) == RB_BLACK)) {
402 SET_RED(w);
403 node = parent;
404 parent = PARENT(parent);
405 left = parent && parent->llink == node;
406 } else {
407 if (w->llink == NULL || COLOR(w->llink) == RB_BLACK) {
408 SET_BLACK(w->rlink);
409 SET_RED(w);
410 rot_left(tree, w); ++rotations;
411 w = parent->llink;
412 }
413 if (COLOR(parent) == RB_RED)
414 SET_RED(w);
415 else
416 SET_BLACK(w);
417 if (w->llink)
418 SET_BLACK(w->llink);
419 SET_BLACK(parent);
420 rot_right(tree, parent); ++rotations;
421 break;
422 }
423 }
424 }
425
426 if (node) {
427 SET_BLACK(node);
428 }
429 return rotations;
430}
431
432size_t rb_tree_count(const rb_tree* tree) { return tree_count(tree); }
436
437size_t
439{
440 if (tree->root == NULL)
441 return 0;
442
443 size_t count = 0;
444 rb_node* node = tree_node_min(tree->root);
445 for (; node != NULL; node = node_next(node)) {
446 ++count;
447 if (!visit(node->key, node->datum, user_data)) break;
448 }
449 return count;
450}
451
452bool
453rb_tree_select(rb_tree *tree, size_t n, const void **key, void **datum)
454{
455 if (n >= tree->count) {
456 if (key)
457 *key = NULL;
458 if (datum)
459 *datum = NULL;
460 return false;
461 }
462 rb_node *node;
463 if (n >= tree->count / 2) {
464 node = tree_node_max(tree->root);
465 n = tree->count - 1 - n;
466 while (n--)
467 node = node_prev(node);
468 } else {
469 node = tree_node_min(tree->root);
470 while (n--)
471 node = node_next(node);
472 }
473 if (key)
474 *key = node->key;
475 if (datum)
476 *datum = node->datum;
477 return true;
478}
479
480static void
481rot_left(rb_tree* tree, rb_node* node)
482{
483 rb_node* const rlink = node->rlink;
484 if ((node->rlink = rlink->llink) != NULL)
485 SET_PARENT(rlink->llink, node);
486 rb_node* const parent = PARENT(node);
487 SET_PARENT(rlink, parent);
488 *(parent ? (parent->llink == node ? &parent->llink : &parent->rlink) : &tree->root) = rlink;
489 rlink->llink = node;
490 SET_PARENT(node, rlink);
491}
492
493static void
494rot_right(rb_tree* tree, rb_node* node)
495{
496 rb_node* const llink = node->llink;
497 if ((node->llink = llink->rlink) != NULL)
498 SET_PARENT(llink->rlink, node);
499 rb_node* const parent = PARENT(node);
500 SET_PARENT(llink, parent);
501 *(parent ? (parent->llink == node ? &parent->llink : &parent->rlink) : &tree->root) = llink;
502 llink->rlink = node;
503 SET_PARENT(node, llink);
504}
505
506static rb_node*
507node_new(void* key)
508{
509 rb_node* node = MALLOC(sizeof(*node));
510 if (node) {
511 /* The low bit of the parent pointer holds the colour, so a node must
512 * be at least 2-byte aligned. dict_malloc_func is user-replaceable,
513 * and an ASSERT would vanish under NDEBUG and let a misaligned
514 * allocator corrupt every parent pointer silently. */
515 if ((((uintptr_t) node) & 1) != 0) {
516 fprintf(stderr, "%s:%d (%s) dict_malloc_func returned an odd "
517 "pointer: %p\n", __FILE__, __LINE__, __func__, (void*) node);
518 abort();
519 }
520 node->key = key;
521 node->datum = NULL;
522 node->color = RB_RED; /* Also initializes parent to NULL */
523 node->llink = NULL;
524 node->rlink = NULL;
525 }
526 return node;
527}
528
529static rb_node*
530node_next(rb_node* node)
531{
532 if (node->rlink) {
533 for (node = node->rlink; node->llink; node = node->llink)
534 /* void */;
535 } else {
536 rb_node* temp = PARENT(node);
537 while (temp && temp->rlink == node) {
538 node = temp;
539 temp = PARENT(temp);
540 }
541 node = temp;
542 }
543
544 return node;
545}
546
547static rb_node*
548node_prev(rb_node* node)
549{
550 if (node->llink) {
551 for (node = node->llink; node->rlink; node = node->rlink)
552 /* void */;
553 } else {
554 rb_node* temp = PARENT(node);
555 while (temp && temp->llink == node) {
556 node = temp;
557 temp = PARENT(temp);
558 }
559 node = temp;
560 }
561
562 return node;
563}
564
565static bool
566node_verify(const rb_tree* tree, const rb_node* parent, const rb_node* node,
567 unsigned black_node_count, unsigned leaf_black_node_count,
568 const void* lower, const void* upper, size_t* count)
569{
570 if (parent == NULL) {
571 VERIFY(tree->root == node);
572 VERIFY(node == NULL || COLOR(node) == RB_BLACK);
573 } else {
574 VERIFY(parent->llink == node || parent->rlink == node);
575 }
576 if (!node) {
577 /* NIL is the leaf for black-height purposes, so the comparison
578 * belongs here. Checking only at nodes with no children left every
579 * path that terminates at the absent child of a *one-child* node
580 * unverified -- which is most of them. */
581 VERIFY(black_node_count == leaf_black_node_count);
582 return true;
583 }
584 VERIFY(PARENT(node) == parent);
585 /* Global BST ordering. Comparing a node only against its immediate parent
586 * would accept an entire subtree placed on the wrong side. */
587 if (lower)
588 VERIFY(tree->cmp_func(lower, node->key) < 0);
589 if (upper)
590 VERIFY(tree->cmp_func(upper, node->key) > 0);
591 if (COLOR(node) == RB_RED) {
592 /* Verify that every child of a red node is black. */
593 if (node->llink)
594 VERIFY(COLOR(node->llink) == RB_BLACK);
595 if (node->rlink)
596 VERIFY(COLOR(node->rlink) == RB_BLACK);
597 } else {
598 black_node_count++;
599 }
600 *count += 1;
601 bool l = node_verify(tree, node, node->llink, black_node_count,
602 leaf_black_node_count, lower, node->key, count);
603 bool r = node_verify(tree, node, node->rlink, black_node_count,
604 leaf_black_node_count, node->key, upper, count);
605 return l && r;
606}
607
608bool
610{
611 if (tree->root)
613 unsigned leaf_black_node_count = 0;
614 if (tree->root) {
615 VERIFY(tree->count > 0);
616 for (rb_node* node = tree->root; node; node = node->llink)
617 if (COLOR(node) == RB_BLACK)
618 leaf_black_node_count++;
619 } else {
620 VERIFY(tree->count == 0);
621 }
622 size_t count = 0;
623 if (!node_verify(tree, NULL, tree->root, 0, leaf_black_node_count,
624 NULL, NULL, &count))
625 return false;
626 VERIFY(tree->count == count);
627 return true;
628}
629
630rb_itor*
632{
633 rb_itor* itor = MALLOC(sizeof(*itor));
634 if (itor) {
635 itor->tree = tree;
636 itor->node = NULL;
637 }
638 return itor;
639}
640
643{
644 dict_itor* itor = MALLOC(sizeof(*itor));
645 if (itor) {
646 if (!(itor->_itor = rb_itor_new(tree))) {
647 FREE(itor);
648 return NULL;
649 }
650 itor->_vtable = &rb_tree_itor_vtable;
651 }
652 return itor;
653}
654
656bool rb_itor_valid(const rb_itor* itor) { return tree_iterator_valid(itor); }
658
659bool
661{
662 if (itor->node)
663 itor->node = node_next(itor->node);
664 return itor->node != NULL;
665}
666
667bool
669{
670 if (itor->node)
671 itor->node = node_prev(itor->node);
672 return itor->node != NULL;
673}
674
675bool
676rb_itor_nextn(rb_itor* itor, size_t count)
677{
678 while (count--) {
679 if (!rb_itor_next(itor))
680 return false;
681 }
682 return itor->node != NULL;
683}
684
685bool
686rb_itor_prevn(rb_itor* itor, size_t count)
687{
688 while (count--) {
689 if (!rb_itor_prev(itor))
690 return false;
691 }
692 return itor->node != NULL;
693}
694
695bool rb_itor_first(rb_itor* itor) { return tree_iterator_first(itor); }
696bool rb_itor_last(rb_itor* itor) { return tree_iterator_last(itor); }
697bool rb_itor_search(rb_itor* itor, const void* key) { return tree_iterator_search(itor, key); }
698bool rb_itor_search_le(rb_itor* itor, const void* key) { return tree_iterator_search_le(itor, key); }
699bool rb_itor_search_lt(rb_itor* itor, const void* key) { return tree_iterator_search_lt(itor, key); }
700bool rb_itor_search_ge(rb_itor* itor, const void* key) { return tree_iterator_search_ge(itor, key); }
701bool rb_itor_search_gt(rb_itor* itor, const void* key) { return tree_iterator_search_gt(itor, key); }
702const void* rb_itor_key(const rb_itor* itor) { return tree_iterator_key(itor); }
703void** rb_itor_datum(rb_itor* itor) { return tree_iterator_datum(itor); }
704int rb_itor_compare(const rb_itor* i1, const rb_itor* i2) { return tree_iterator_compare(i1, i2); }
705
706bool
708{
709 if (!it->node)
710 return false;
711 remove_node(it->tree, it->node);
712 it->node = NULL;
713 return true;
714}
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 ** rb_tree_search_lt(rb_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 rb_tree.c:224
size_t rb_tree_min_path_length(const rb_tree *tree)
Return the shallowest depth at which a child link is absent, the root being at depth 1,...
Definition rb_tree.c:433
bool rb_itor_search_lt(rb_itor *itor, const void *key)
Position |itor| on the greatest key less than |key| and return true, or unposition it and return fals...
Definition rb_tree.c:699
#define PARENT(node)
Definition rb_tree.c:49
bool rb_itor_search_ge(rb_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 rb_tree.c:700
const void * rb_itor_key(const rb_itor *itor)
Return the key |itor| is positioned on, or NULL if it is not positioned.
Definition rb_tree.c:702
rb_tree * rb_tree_new(dict_compare_func cmp_func)
Create an empty tree that orders keys with |cmp_func| (must not be NULL).
Definition rb_tree.c:163
bool rb_itor_next(rb_itor *itor)
Move |itor| to the next element in key order and return true, or unposition it and return false if th...
Definition rb_tree.c:660
bool rb_itor_valid(const rb_itor *itor)
Return whether |itor| is positioned on an element.
Definition rb_tree.c:656
void ** rb_tree_search_ge(rb_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 rb_tree.c:225
dict_itor * rb_dict_itor_new(rb_tree *tree)
Like rb_itor_new(), but wrapped in a generic dict_itor for use with the dict_itor_* macros.
Definition rb_tree.c:642
size_t rb_tree_traverse(rb_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 rb_tree.c:438
size_t rb_tree_total_path_length(const rb_tree *tree)
Return the sum of the depths of all nodes, the root being at depth 1, or 0 for an empty tree.
Definition rb_tree.c:435
void ** rb_tree_search(rb_tree *tree, const void *key)
Return the address of the datum stored for |key|, or NULL if |key| is not present.
Definition rb_tree.c:222
#define SET_BLACK(node)
Definition rb_tree.c:53
bool rb_itor_search_le(rb_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 rb_tree.c:698
void rb_itor_invalidate(rb_itor *itor)
Unposition |itor|, so that it is not positioned on any element.
Definition rb_tree.c:657
size_t rb_tree_clear(rb_tree *tree, dict_delete_func delete_func)
Remove every element, calling |delete_func|(key, datum) for each unless |delete_func| is NULL.
Definition rb_tree.c:199
size_t rb_tree_max_path_length(const rb_tree *tree)
Return the greatest depth of any node, the root being at depth 1, or 0 for an empty tree: the height ...
Definition rb_tree.c:434
rb_itor * rb_itor_new(rb_tree *tree)
Create an iterator over |tree| that is not positioned on any element yet.
Definition rb_tree.c:631
bool rb_itor_remove(rb_itor *it)
Remove the element |itor| is positioned on and unposition |itor|; return false if it was not position...
Definition rb_tree.c:707
bool rb_itor_prevn(rb_itor *itor, size_t count)
Move |itor| |count| elements back and return whether it is still positioned.
Definition rb_tree.c:686
bool rb_itor_search(rb_itor *itor, const void *key)
Position |itor| on |key| and return true, or unposition it and return false if |key| is not present.
Definition rb_tree.c:697
bool rb_itor_prev(rb_itor *itor)
Move |itor| to the previous element in key order and return true, or unposition it and return false i...
Definition rb_tree.c:668
#define SET_PARENT(node, p)
Definition rb_tree.c:54
#define SET_RED(node)
Definition rb_tree.c:52
void ** rb_itor_datum(rb_itor *itor)
Return the address of the datum |itor| is positioned on, through which it can be read or replaced,...
Definition rb_tree.c:703
bool rb_itor_first(rb_itor *itor)
Position |itor| on the first element in key order and return true, or unposition it and return false ...
Definition rb_tree.c:695
size_t rb_tree_free(rb_tree *tree, dict_delete_func delete_func)
Remove every element, calling |delete_func|(key, datum) for each unless |delete_func| is NULL,...
Definition rb_tree.c:192
bool rb_itor_nextn(rb_itor *itor, size_t count)
Move |itor| |count| elements forward and return whether it is still positioned.
Definition rb_tree.c:676
void rb_itor_free(rb_itor *itor)
Free an iterator.
Definition rb_tree.c:655
#define RB_BLACK
Definition rb_tree.c:47
bool rb_itor_last(rb_itor *itor)
Position |itor| on the last element in key order and return true, or unposition it and return false i...
Definition rb_tree.c:696
dict_insert_result rb_tree_insert(rb_tree *tree, void *key)
Insert |key| unless an equal key is present.
Definition rb_tree.c:229
bool rb_tree_verify(const rb_tree *tree)
Check the internal invariants of the tree and return true if they hold, or print the first failed che...
Definition rb_tree.c:609
void ** rb_tree_search_le(rb_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 rb_tree.c:223
size_t rb_tree_count(const rb_tree *tree)
Return the number of elements.
Definition rb_tree.c:432
dict * rb_dict_new(dict_compare_func cmp_func)
Like rb_tree_new(), but wrapped in a generic dict for use with the dict_* macros.
Definition rb_tree.c:178
dict_remove_result rb_tree_remove(rb_tree *tree, const void *key)
Remove the element with key |key|.
Definition rb_tree.c:346
bool rb_tree_select(rb_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 rb_tree.c:453
#define COLOR(node)
Definition rb_tree.c:50
#define RB_RED
Definition rb_tree.c:46
bool rb_itor_search_gt(rb_itor *itor, const void *key)
Position |itor| on the least key greater than |key| and return true, or unposition it and return fals...
Definition rb_tree.c:701
void ** rb_tree_search_gt(rb_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 rb_tree.c:226
int rb_itor_compare(const rb_itor *i1, const rb_itor *i2)
Compare the positions of two iterators over the same tree: return a negative value,...
Definition rb_tree.c:704
Red-black 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
rb_tree * tree
Definition rb_tree.c:81
rb_node * node
Definition rb_tree.c:81
rb_node * rlink
Definition rb_tree.c:43
void * datum
Definition rb_tree.c:40
rb_node * llink
Definition rb_tree.c:42
void * key
Definition rb_tree.c:39
intptr_t color
Definition rb_tree.c:41
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)
void ** tree_iterator_datum(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_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)
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)
size_t tree_total_path_length(const void *Tree)
bool tree_iterator_first(void *Iterator)
void tree_iterator_free(void *Iterator)
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)
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_search_le(void *Tree, const void *key)
bool tree_iterator_search(void *Iterator, const void *key)
#define TREE_ITERATOR_FIELDS(tree_type, node_type)
Definition tree_common.h:54
#define TREE_FIELDS(node_type)
Definition tree_common.h:44