├── Readme.md
├── rb_tree.h
└── rb_tree.c
/Readme.md:
--------------------------------------------------------------------------------
1 | # Red-black tree C implementation
2 |
3 | Based on Julienne Walker's red-black tree implementation.
4 |
5 | ## Usage
6 |
7 | First, grab the source into your project, you'll need just those two:
8 |
9 | wget https://raw.github.com/mirek/rb_tree/master/rb_tree.h
10 | wget https://raw.github.com/mirek/rb_tree/master/rb_tree.c
11 |
12 | Let's say you want to store `struct iovec` objects (defined in `sys/uio.h`) with the following definition:
13 |
14 | struct iovec {
15 | void *iov_base; // [XSI] Base address of I/O memory region
16 | size_t iov_len; // [XSI] Size of region iov_base points to
17 | };
18 |
19 | You'll need to provide comparison callback for your object. Let's say you want to keep track
20 | of the length of the iovec buffers, your callback should look similar to:
21 |
22 | int
23 | my_cmp_cb (struct rb_tree *self, struct rb_node *node_a, struct rb_node *node_b) {
24 | struct iovec *a = (struct iovec *) node_a->value;
25 | struct iovec *b = (struct iovec *) node_b->value;
26 | return (a->iov_len > b->iov_len) - (a->iov_len < b->iov_len);
27 | }
28 |
29 | To create your red-black tree:
30 |
31 | struct rb_tree *tree = rb_tree_create(my_cmp_cb);
32 | if (tree) {
33 |
34 | // Use the tree here...
35 | for (int i = 0; i < 10; i++) {
36 | struct iovec *v = malloc(sizeof *v);
37 | v->iov_base = (void *) i;
38 | v->iov_len = i * i;
39 |
40 | // Default insert, which allocates internal rb_nodes for you.
41 | rb_tree_insert(tree, v);
42 | }
43 |
44 | // To f
45 | struct iovec *f = rb_tree_find(tree, & (struct iovec) { .iov_base = (void *) 7, .iov_len = 0 });
46 | if (r) {
47 | fprintf(stdout, "found iovec(.iov_base = %p, .iov_len = %zu)\n", f->iov_base, f->iov_len)
48 | } else {
49 | printf("not found\n");
50 | }
51 |
52 | // Dealloc call can take optional parameter to notify on each node
53 | // being deleted so you can free the node and/or your object:
54 | rb_tree_dealloc(tree, NULL);
55 | }
56 |
57 | Above example will leak because malloc is not balanced with free.
58 |
59 | If you want to iterate over elements (here in reverse order):
60 |
61 | struct rb_iter *iter = rb_iter_create();
62 | if (iter) {
63 | for (struct iovec *v = rb_iter_last(iter, tree); v; v = rb_iter_prev(iter)) {
64 | printf("- %p %zu\n", v->iov_base, v->iov_len);
65 | }
66 | rb_iter_dealloc(iter);
67 | }
68 |
69 | ## License
70 |
71 | None (Public Domain).
72 |
--------------------------------------------------------------------------------
/rb_tree.h:
--------------------------------------------------------------------------------
1 | //
2 | // Based on Julienne Walker's rb_tree
3 | // implementation.
4 | //
5 | // Modified by Mirek Rusin .
6 | //
7 | // This is free and unencumbered software released into the public domain.
8 | //
9 | // Anyone is free to copy, modify, publish, use, compile, sell, or
10 | // distribute this software, either in source code form or as a compiled
11 | // binary, for any purpose, commercial or non-commercial, and by any
12 | // means.
13 | //
14 | // In jurisdictions that recognize copyright laws, the author or authors
15 | // of this software dedicate any and all copyright interest in the
16 | // software to the public domain. We make this dedication for the benefit
17 | // of the public at large and to the detriment of our heirs and
18 | // successors. We intend this dedication to be an overt act of
19 | // relinquishment in perpetuity of all present and future rights to this
20 | // software under copyright law.
21 | //
22 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
25 | // IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
26 | // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
27 | // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28 | // OTHER DEALINGS IN THE SOFTWARE.
29 | //
30 | // For more information, please refer to
31 | //
32 |
33 | #ifndef __RB_TREE_H__
34 | #define __RB_TREE_H__ 1
35 |
36 | #include
37 | #include
38 | #include
39 | #include
40 |
41 | #ifndef RB_ITER_MAX_HEIGHT
42 | #define RB_ITER_MAX_HEIGHT 64 // Tallest allowable tree to iterate
43 | #endif
44 |
45 | struct rb_node;
46 | struct rb_tree;
47 |
48 | typedef int (*rb_tree_node_cmp_f) (struct rb_tree *self, struct rb_node *a, struct rb_node *b);
49 | typedef void (*rb_tree_node_f) (struct rb_tree *self, struct rb_node *node);
50 |
51 | struct rb_node {
52 | int red; // Color red (1), black (0)
53 | struct rb_node *link[2]; // Link left [0] and right [1]
54 | void *value; // User provided, used indirectly via rb_tree_node_cmp_f.
55 | };
56 |
57 | struct rb_tree {
58 | struct rb_node *root;
59 | rb_tree_node_cmp_f cmp;
60 | size_t size;
61 | void *info; // User provided, not used by rb_tree.
62 | };
63 |
64 | struct rb_iter {
65 | struct rb_tree *tree;
66 | struct rb_node *node; // Current node
67 | struct rb_node *path[RB_ITER_MAX_HEIGHT]; // Traversal path
68 | size_t top; // Top of stack
69 | void *info; // User provided, not used by rb_iter.
70 | };
71 |
72 | int rb_tree_node_cmp_ptr_cb (struct rb_tree *self, struct rb_node *a, struct rb_node *b);
73 | void rb_tree_node_dealloc_cb (struct rb_tree *self, struct rb_node *node);
74 |
75 | struct rb_node *rb_node_alloc ();
76 | struct rb_node *rb_node_create (void *value);
77 | struct rb_node *rb_node_init (struct rb_node *self, void *value);
78 | void rb_node_dealloc (struct rb_node *self);
79 |
80 | struct rb_tree *rb_tree_alloc ();
81 | struct rb_tree *rb_tree_create (rb_tree_node_cmp_f cmp);
82 | struct rb_tree *rb_tree_init (struct rb_tree *self, rb_tree_node_cmp_f cmp);
83 | void rb_tree_dealloc (struct rb_tree *self, rb_tree_node_f node_cb);
84 | void *rb_tree_find (struct rb_tree *self, void *value);
85 | int rb_tree_insert (struct rb_tree *self, void *value);
86 | int rb_tree_remove (struct rb_tree *self, void *value);
87 | size_t rb_tree_size (struct rb_tree *self);
88 |
89 | int rb_tree_insert_node (struct rb_tree *self, struct rb_node *node);
90 | int rb_tree_remove_with_cb (struct rb_tree *self, void *value, rb_tree_node_f node_cb);
91 |
92 | int rb_tree_test (struct rb_tree *self, struct rb_node *root);
93 |
94 | struct rb_iter *rb_iter_alloc ();
95 | struct rb_iter *rb_iter_init ();
96 | struct rb_iter *rb_iter_create ();
97 | void rb_iter_dealloc (struct rb_iter *self);
98 | void *rb_iter_first (struct rb_iter *self, struct rb_tree *tree);
99 | void *rb_iter_last (struct rb_iter *self, struct rb_tree *tree);
100 | void *rb_iter_next (struct rb_iter *self);
101 | void *rb_iter_prev (struct rb_iter *self);
102 |
103 | #endif
104 |
--------------------------------------------------------------------------------
/rb_tree.c:
--------------------------------------------------------------------------------
1 | //
2 | // Based on Julienne Walker's rb_tree
3 | // implementation.
4 | //
5 | // Modified by Mirek Rusin .
6 | //
7 | // This is free and unencumbered software released into the public domain.
8 | //
9 | // Anyone is free to copy, modify, publish, use, compile, sell, or
10 | // distribute this software, either in source code form or as a compiled
11 | // binary, for any purpose, commercial or non-commercial, and by any
12 | // means.
13 | //
14 | // In jurisdictions that recognize copyright laws, the author or authors
15 | // of this software dedicate any and all copyright interest in the
16 | // software to the public domain. We make this dedication for the benefit
17 | // of the public at large and to the detriment of our heirs and
18 | // successors. We intend this dedication to be an overt act of
19 | // relinquishment in perpetuity of all present and future rights to this
20 | // software under copyright law.
21 | //
22 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
25 | // IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
26 | // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
27 | // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28 | // OTHER DEALINGS IN THE SOFTWARE.
29 | //
30 | // For more information, please refer to
31 | //
32 |
33 | #include "rb_tree.h"
34 |
35 | // rb_node
36 |
37 | struct rb_node *
38 | rb_node_alloc () {
39 | return malloc(sizeof(struct rb_node));
40 | }
41 |
42 | struct rb_node *
43 | rb_node_init (struct rb_node *self, void *value) {
44 | if (self) {
45 | self->red = 1;
46 | self->link[0] = self->link[1] = NULL;
47 | self->value = value;
48 | }
49 | return self;
50 | }
51 |
52 | struct rb_node *
53 | rb_node_create (void *value) {
54 | return rb_node_init(rb_node_alloc(), value);
55 | }
56 |
57 | void
58 | rb_node_dealloc (struct rb_node *self) {
59 | if (self) {
60 | free(self);
61 | }
62 | }
63 |
64 | static int
65 | rb_node_is_red (const struct rb_node *self) {
66 | return self ? self->red : 0;
67 | }
68 |
69 | static struct rb_node *
70 | rb_node_rotate (struct rb_node *self, int dir) {
71 | struct rb_node *result = NULL;
72 | if (self) {
73 | result = self->link[!dir];
74 | self->link[!dir] = result->link[dir];
75 | result->link[dir] = self;
76 | self->red = 1;
77 | result->red = 0;
78 | }
79 | return result;
80 | }
81 |
82 | static struct rb_node *
83 | rb_node_rotate2 (struct rb_node *self, int dir) {
84 | struct rb_node *result = NULL;
85 | if (self) {
86 | self->link[!dir] = rb_node_rotate(self->link[!dir], !dir);
87 | result = rb_node_rotate(self, dir);
88 | }
89 | return result;
90 | }
91 |
92 | // rb_tree - default callbacks
93 |
94 | int
95 | rb_tree_node_cmp_ptr_cb (struct rb_tree *self, struct rb_node *a, struct rb_node *b) {
96 | return (a->value > b->value) - (a->value < b->value);
97 | }
98 |
99 | void
100 | rb_tree_node_dealloc_cb (struct rb_tree *self, struct rb_node *node) {
101 | if (self) {
102 | if (node) {
103 | rb_node_dealloc(node);
104 | }
105 | }
106 | }
107 |
108 | // rb_tree
109 |
110 | struct rb_tree *
111 | rb_tree_alloc () {
112 | return malloc(sizeof(struct rb_tree));
113 | }
114 |
115 | struct rb_tree *
116 | rb_tree_init (struct rb_tree *self, rb_tree_node_cmp_f node_cmp_cb) {
117 | if (self) {
118 | self->root = NULL;
119 | self->size = 0;
120 | self->cmp = node_cmp_cb ? node_cmp_cb : rb_tree_node_cmp_ptr_cb;
121 | }
122 | return self;
123 | }
124 |
125 | struct rb_tree *
126 | rb_tree_create (rb_tree_node_cmp_f node_cb) {
127 | return rb_tree_init(rb_tree_alloc(), node_cb);
128 | }
129 |
130 | void
131 | rb_tree_dealloc (struct rb_tree *self, rb_tree_node_f node_cb) {
132 | if (self) {
133 | if (node_cb) {
134 | struct rb_node *node = self->root;
135 | struct rb_node *save = NULL;
136 |
137 | // Rotate away the left links so that
138 | // we can treat this like the destruction
139 | // of a linked list
140 | while (node) {
141 | if (node->link[0] == NULL) {
142 |
143 | // No left links, just kill the node and move on
144 | save = node->link[1];
145 | node_cb(self, node);
146 | node = NULL;
147 | } else {
148 |
149 | // Rotate away the left link and check again
150 | save = node->link[0];
151 | node->link[0] = save->link[1];
152 | save->link[1] = node;
153 | }
154 | node = save;
155 | }
156 | }
157 | free(self);
158 | }
159 | }
160 |
161 | int
162 | rb_tree_test (struct rb_tree *self, struct rb_node *root) {
163 | int lh, rh;
164 |
165 | if ( root == NULL )
166 | return 1;
167 | else {
168 | struct rb_node *ln = root->link[0];
169 | struct rb_node *rn = root->link[1];
170 |
171 | /* Consecutive red links */
172 | if (rb_node_is_red(root)) {
173 | if (rb_node_is_red(ln) || rb_node_is_red(rn)) {
174 | printf("Red violation");
175 | return 0;
176 | }
177 | }
178 |
179 | lh = rb_tree_test(self, ln);
180 | rh = rb_tree_test(self, rn);
181 |
182 | /* Invalid binary search tree */
183 | if ( ( ln != NULL && self->cmp(self, ln, root) >= 0 )
184 | || ( rn != NULL && self->cmp(self, rn, root) <= 0))
185 | {
186 | puts ( "Binary tree violation" );
187 | return 0;
188 | }
189 |
190 | /* Black height mismatch */
191 | if ( lh != 0 && rh != 0 && lh != rh ) {
192 | puts ( "Black violation" );
193 | return 0;
194 | }
195 |
196 | /* Only count black links */
197 | if ( lh != 0 && rh != 0 )
198 | return rb_node_is_red ( root ) ? lh : lh + 1;
199 | else
200 | return 0;
201 | }
202 | }
203 |
204 | void *
205 | rb_tree_find(struct rb_tree *self, void *value) {
206 | void *result = NULL;
207 | if (self) {
208 | struct rb_node node = { .value = value };
209 | struct rb_node *it = self->root;
210 | int cmp = 0;
211 | while (it) {
212 | if ((cmp = self->cmp(self, it, &node))) {
213 |
214 | // If the tree supports duplicates, they should be
215 | // chained to the right subtree for this to work
216 | it = it->link[cmp < 0];
217 | } else {
218 | break;
219 | }
220 | }
221 | result = it ? it->value : NULL;
222 | }
223 | return result;
224 | }
225 |
226 | // Creates (malloc'ates)
227 | int
228 | rb_tree_insert (struct rb_tree *self, void *value) {
229 | return rb_tree_insert_node(self, rb_node_create(value));
230 | }
231 |
232 | // Returns 1 on success, 0 otherwise.
233 | int
234 | rb_tree_insert_node (struct rb_tree *self, struct rb_node *node) {
235 | int result = 0;
236 | if (self && node) {
237 | if (self->root == NULL) {
238 | self->root = node;
239 | result = 1;
240 | } else {
241 | struct rb_node head = { 0 }; // False tree root
242 | struct rb_node *g, *t; // Grandparent & parent
243 | struct rb_node *p, *q; // Iterator & parent
244 | int dir = 0, last = 0;
245 |
246 | // Set up our helpers
247 | t = &head;
248 | g = p = NULL;
249 | q = t->link[1] = self->root;
250 |
251 | // Search down the tree for a place to insert
252 | while (1) {
253 | if (q == NULL) {
254 |
255 | // Insert node at the first null link.
256 | p->link[dir] = q = node;
257 | } else if (rb_node_is_red(q->link[0]) && rb_node_is_red(q->link[1])) {
258 |
259 | // Simple red violation: color flip
260 | q->red = 1;
261 | q->link[0]->red = 0;
262 | q->link[1]->red = 0;
263 | }
264 |
265 | if (rb_node_is_red(q) && rb_node_is_red(p)) {
266 |
267 | // Hard red violation: rotations necessary
268 | int dir2 = t->link[1] == g;
269 | if (q == p->link[last]) {
270 | t->link[dir2] = rb_node_rotate(g, !last);
271 | } else {
272 | t->link[dir2] = rb_node_rotate2(g, !last);
273 | }
274 | }
275 |
276 | // Stop working if we inserted a node. This
277 | // check also disallows duplicates in the tree
278 | if (self->cmp(self, q, node) == 0) {
279 | break;
280 | }
281 |
282 | last = dir;
283 | dir = self->cmp(self, q, node) < 0;
284 |
285 | // Move the helpers down
286 | if (g != NULL) {
287 | t = g;
288 | }
289 |
290 | g = p, p = q;
291 | q = q->link[dir];
292 | }
293 |
294 | // Update the root (it may be different)
295 | self->root = head.link[1];
296 | }
297 |
298 | // Make the root black for simplified logic
299 | self->root->red = 0;
300 | ++self->size;
301 | }
302 |
303 | return 1;
304 | }
305 |
306 | // Returns 1 if the value was removed, 0 otherwise. Optional node callback
307 | // can be provided to dealloc node and/or user data. Use rb_tree_node_dealloc
308 | // default callback to deallocate node created by rb_tree_insert(...).
309 | int
310 | rb_tree_remove_with_cb (struct rb_tree *self, void *value, rb_tree_node_f node_cb) {
311 | if (self->root != NULL) {
312 | struct rb_node head = {0}; // False tree root
313 | struct rb_node node = { .value = value }; // Value wrapper node
314 | struct rb_node *q, *p, *g; // Helpers
315 | struct rb_node *f = NULL; // Found item
316 | int dir = 1;
317 |
318 | // Set up our helpers
319 | q = &head;
320 | g = p = NULL;
321 | q->link[1] = self->root;
322 |
323 | // Search and push a red node down
324 | // to fix red violations as we go
325 | while (q->link[dir] != NULL) {
326 | int last = dir;
327 |
328 | // Move the helpers down
329 | g = p, p = q;
330 | q = q->link[dir];
331 | dir = self->cmp(self, q, &node) < 0;
332 |
333 | // Save the node with matching value and keep
334 | // going; we'll do removal tasks at the end
335 | if (self->cmp(self, q, &node) == 0) {
336 | f = q;
337 | }
338 |
339 | // Push the red node down with rotations and color flips
340 | if (!rb_node_is_red(q) && !rb_node_is_red(q->link[dir])) {
341 | if (rb_node_is_red(q->link[!dir])) {
342 | p = p->link[last] = rb_node_rotate(q, dir);
343 | } else if (!rb_node_is_red(q->link[!dir])) {
344 | struct rb_node *s = p->link[!last];
345 | if (s) {
346 | if (!rb_node_is_red(s->link[!last]) && !rb_node_is_red(s->link[last])) {
347 |
348 | // Color flip
349 | p->red = 0;
350 | s->red = 1;
351 | q->red = 1;
352 | } else {
353 | int dir2 = g->link[1] == p;
354 | if (rb_node_is_red(s->link[last])) {
355 | g->link[dir2] = rb_node_rotate2(p, last);
356 | } else if (rb_node_is_red(s->link[!last])) {
357 | g->link[dir2] = rb_node_rotate(p, last);
358 | }
359 |
360 | // Ensure correct coloring
361 | q->red = g->link[dir2]->red = 1;
362 | g->link[dir2]->link[0]->red = 0;
363 | g->link[dir2]->link[1]->red = 0;
364 | }
365 | }
366 | }
367 | }
368 | }
369 |
370 | // Replace and remove the saved node
371 | if (f) {
372 | void *tmp = f->value;
373 | f->value = q->value;
374 | q->value = tmp;
375 |
376 | p->link[p->link[1] == q] = q->link[q->link[0] == NULL];
377 |
378 | if (node_cb) {
379 | node_cb(self, q);
380 | }
381 | q = NULL;
382 | }
383 |
384 | // Update the root (it may be different)
385 | self->root = head.link[1];
386 |
387 | // Make the root black for simplified logic
388 | if (self->root != NULL) {
389 | self->root->red = 0;
390 | }
391 |
392 | --self->size;
393 | }
394 | return 1;
395 | }
396 |
397 | int
398 | rb_tree_remove (struct rb_tree *self, void *value) {
399 | int result = 0;
400 | if (self) {
401 | result = rb_tree_remove_with_cb(self, value, rb_tree_node_dealloc_cb);
402 | }
403 | return result;
404 | }
405 |
406 | size_t
407 | rb_tree_size (struct rb_tree *self) {
408 | size_t result = 0;
409 | if (self) {
410 | result = self->size;
411 | }
412 | return result;
413 | }
414 |
415 | // rb_iter
416 |
417 | struct rb_iter *
418 | rb_iter_alloc () {
419 | return malloc(sizeof(struct rb_iter));
420 | }
421 |
422 | struct rb_iter *
423 | rb_iter_init (struct rb_iter *self) {
424 | if (self) {
425 | self->tree = NULL;
426 | self->node = NULL;
427 | self->top = 0;
428 | }
429 | return self;
430 | }
431 |
432 | struct rb_iter *
433 | rb_iter_create () {
434 | return rb_iter_init(rb_iter_alloc());
435 | }
436 |
437 | void
438 | rb_iter_dealloc (struct rb_iter *self) {
439 | if (self) {
440 | free(self);
441 | }
442 | }
443 |
444 | // Internal function, init traversal object, dir determines whether
445 | // to begin traversal at the smallest or largest valued node.
446 | static void *
447 | rb_iter_start (struct rb_iter *self, struct rb_tree *tree, int dir) {
448 | void *result = NULL;
449 | if (self) {
450 | self->tree = tree;
451 | self->node = tree->root;
452 | self->top = 0;
453 |
454 | // Save the path for later selfersal
455 | if (self->node != NULL) {
456 | while (self->node->link[dir] != NULL) {
457 | self->path[self->top++] = self->node;
458 | self->node = self->node->link[dir];
459 | }
460 | }
461 |
462 | result = self->node == NULL ? NULL : self->node->value;
463 | }
464 | return result;
465 | }
466 |
467 | // Traverse a red black tree in the user-specified direction (0 asc, 1 desc)
468 | static void *
469 | rb_iter_move (struct rb_iter *self, int dir) {
470 | if (self->node->link[dir] != NULL) {
471 |
472 | // Continue down this branch
473 | self->path[self->top++] = self->node;
474 | self->node = self->node->link[dir];
475 | while ( self->node->link[!dir] != NULL ) {
476 | self->path[self->top++] = self->node;
477 | self->node = self->node->link[!dir];
478 | }
479 | } else {
480 |
481 | // Move to the next branch
482 | struct rb_node *last = NULL;
483 | do {
484 | if (self->top == 0) {
485 | self->node = NULL;
486 | break;
487 | }
488 | last = self->node;
489 | self->node = self->path[--self->top];
490 | } while (last == self->node->link[dir]);
491 | }
492 | return self->node == NULL ? NULL : self->node->value;
493 | }
494 |
495 | void *
496 | rb_iter_first (struct rb_iter *self, struct rb_tree *tree) {
497 | return rb_iter_start(self, tree, 0);
498 | }
499 |
500 | void *
501 | rb_iter_last (struct rb_iter *self, struct rb_tree *tree) {
502 | return rb_iter_start(self, tree, 1);
503 | }
504 |
505 | void *
506 | rb_iter_next (struct rb_iter *self) {
507 | return rb_iter_move(self, 1);
508 | }
509 |
510 | void *
511 | rb_iter_prev (struct rb_iter *self) {
512 | return rb_iter_move(self, 0);
513 | }
514 |
--------------------------------------------------------------------------------