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