├── 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 | --------------------------------------------------------------------------------