1 /*
2  * Copyright (c) 2015 Cray Inc. All rights reserved.
3  *
4  * This software is available to you under a choice of one of two
5  * licenses.  You may choose to be licensed under the terms of the GNU
6  * General Public License (GPL) Version 2, available from the file
7  * COPYING in the main directory of this source tree, or the
8  * BSD license below:
9  *
10  *     Redistribution and use in source and binary forms, with or
11  *     without modification, are permitted provided that the following
12  *     conditions are met:
13  *
14  *      - Redistributions of source code must retain the above
15  *        copyright notice, this list of conditions and the following
16  *        disclaimer.
17  *
18  *      - Redistributions in binary form must reproduce the above
19  *        copyright notice, this list of conditions and the following
20  *        disclaimer in the documentation and/or other materials
21  *        provided with the distribution.
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
26  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30  * SOFTWARE.
31  */
32 
33 /*
34  * Copied from http://oopweb.com/Algorithms/Documents/Sman/VolumeFrames.html?/Algorithms/Documents/Sman/Volume/RedBlackTrees_files/s_rbt.htm
35  *
36  * Disclosure from the author's main page:
37  * (http://oopweb.com/Algorithms/Documents/Sman/VolumeFrames.html?/Algorithms/Documents/Sman/Volume/RedBlackTrees_files/s_rbt.htm)
38  *
39  *     Source code when part of a software project may be used freely
40  *     without reference to the author.
41  *
42  */
43 
44 // reentrant red-black tree
45 
46 #include <stdlib.h>
47 #include "rbtree.h"
48 
49 typedef enum { BLACK, RED } NodeColor;
50 
51 typedef struct NodeTag {
52     struct NodeTag *left;       // left child
53     struct NodeTag *right;      // right child
54     struct NodeTag *parent;     // parent
55     NodeColor color;            // node color (BLACK, RED)
56     void *key;                  // key used for searching
57     void *val;                // user data
58 } NodeType;
59 
60 typedef struct RbtTag {
61     NodeType *root;   // root of red-black tree
62     NodeType sentinel;
63     int (*compare)(void *a, void *b);    // compare keys
64 } RbtType;
65 
66 // all leafs are sentinels
67 #define SENTINEL &rbt->sentinel
68 
rbtNew(int (* rbtCompare)(void * a,void * b))69 RbtHandle rbtNew(int(*rbtCompare)(void *a, void *b)) {
70     RbtType *rbt;
71 
72     if ((rbt = (RbtType *)malloc(sizeof(RbtType))) == NULL) {
73         return NULL;
74     }
75 
76     rbt->compare = rbtCompare;
77     rbt->root = SENTINEL;
78     rbt->sentinel.left = SENTINEL;
79     rbt->sentinel.right = SENTINEL;
80     rbt->sentinel.parent = NULL;
81     rbt->sentinel.color = BLACK;
82     rbt->sentinel.key = NULL;
83     rbt->sentinel.val = NULL;
84 
85     return rbt;
86 }
87 
deleteTree(RbtHandle h,NodeType * p)88 static void deleteTree(RbtHandle h, NodeType *p) {
89     RbtType *rbt = h;
90 
91     // erase nodes depth-first
92     if (p == SENTINEL) return;
93     deleteTree(h, p->left);
94     deleteTree(h, p->right);
95     free(p);
96 }
97 
rbtDelete(RbtHandle h)98 void rbtDelete(RbtHandle h) {
99     RbtType *rbt = h;
100 
101     deleteTree(h, rbt->root);
102     free(rbt);
103 }
104 
rotateLeft(RbtType * rbt,NodeType * x)105 static void rotateLeft(RbtType *rbt, NodeType *x) {
106 
107     // rotate node x to left
108 
109     NodeType *y = x->right;
110 
111     // establish x->right link
112     x->right = y->left;
113     if (y->left != SENTINEL) y->left->parent = x;
114 
115     // establish y->parent link
116     if (y != SENTINEL) y->parent = x->parent;
117     if (x->parent) {
118         if (x == x->parent->left)
119             x->parent->left = y;
120         else
121             x->parent->right = y;
122     } else {
123         rbt->root = y;
124     }
125 
126     // link x and y
127     y->left = x;
128     if (x != SENTINEL) x->parent = y;
129 }
130 
rotateRight(RbtType * rbt,NodeType * x)131 static void rotateRight(RbtType *rbt, NodeType *x) {
132 
133     // rotate node x to right
134 
135     NodeType *y = x->left;
136 
137     // establish x->left link
138     x->left = y->right;
139     if (y->right != SENTINEL) y->right->parent = x;
140 
141     // establish y->parent link
142     if (y != SENTINEL) y->parent = x->parent;
143     if (x->parent) {
144         if (x == x->parent->right)
145             x->parent->right = y;
146         else
147             x->parent->left = y;
148     } else {
149         rbt->root = y;
150     }
151 
152     // link x and y
153     y->right = x;
154     if (x != SENTINEL) x->parent = y;
155 }
156 
insertFixup(RbtType * rbt,NodeType * x)157 static void insertFixup(RbtType *rbt, NodeType *x) {
158 
159     // maintain red-black tree balance after inserting node x
160 
161     // check red-black properties
162     while (x != rbt->root && x->parent->color == RED) {
163         // we have a violation
164         if (x->parent == x->parent->parent->left) {
165             NodeType *y = x->parent->parent->right;
166             if (y->color == RED) {
167 
168                 // uncle is RED
169                 x->parent->color = BLACK;
170                 y->color = BLACK;
171                 x->parent->parent->color = RED;
172                 x = x->parent->parent;
173             } else {
174 
175                 // uncle is BLACK
176                 if (x == x->parent->right) {
177                     // make x a left child
178                     x = x->parent;
179                     rotateLeft(rbt, x);
180                 }
181 
182                 // recolor and rotate
183                 x->parent->color = BLACK;
184                 x->parent->parent->color = RED;
185                 rotateRight(rbt, x->parent->parent);
186             }
187         } else {
188 
189             // mirror image of above code
190             NodeType *y = x->parent->parent->left;
191             if (y->color == RED) {
192 
193                 // uncle is RED
194                 x->parent->color = BLACK;
195                 y->color = BLACK;
196                 x->parent->parent->color = RED;
197                 x = x->parent->parent;
198             } else {
199 
200                 // uncle is BLACK
201                 if (x == x->parent->left) {
202                     x = x->parent;
203                     rotateRight(rbt, x);
204                 }
205                 x->parent->color = BLACK;
206                 x->parent->parent->color = RED;
207                 rotateLeft(rbt, x->parent->parent);
208             }
209         }
210     }
211     rbt->root->color = BLACK;
212 }
213 
rbtInsert(RbtHandle h,void * key,void * val)214 RbtStatus rbtInsert(RbtHandle h, void *key, void *val) {
215     NodeType *current, *parent, *x;
216     RbtType *rbt = h;
217 
218     // allocate node for data and insert in tree
219 
220     // find future parent
221     current = rbt->root;
222     parent = 0;
223     while (current != SENTINEL) {
224         int rc = rbt->compare(key, current->key);
225         if (rc == 0)
226             return RBT_STATUS_DUPLICATE_KEY;
227         parent = current;
228         current = (rc < 0) ? current->left : current->right;
229     }
230 
231     // setup new node
232     if ((x = malloc (sizeof(*x))) == 0)
233         return RBT_STATUS_MEM_EXHAUSTED;
234     x->parent = parent;
235     x->left = SENTINEL;
236     x->right = SENTINEL;
237     x->color = RED;
238     x->key = key;
239     x->val = val;
240 
241     // insert node in tree
242     if(parent) {
243         if(rbt->compare(key, parent->key) < 0)
244             parent->left = x;
245         else
246             parent->right = x;
247     } else {
248         rbt->root = x;
249     }
250 
251     insertFixup(rbt, x);
252 
253     return RBT_STATUS_OK;
254 }
255 
deleteFixup(RbtType * rbt,NodeType * x)256 static void deleteFixup(RbtType *rbt, NodeType *x) {
257 
258     // maintain red-black tree balance after deleting node x
259 
260     while (x != rbt->root && x->color == BLACK) {
261         if (x == x->parent->left) {
262             NodeType *w = x->parent->right;
263             if (w->color == RED) {
264                 w->color = BLACK;
265                 x->parent->color = RED;
266                 rotateLeft (rbt, x->parent);
267                 w = x->parent->right;
268             }
269             if (w->left->color == BLACK && w->right->color == BLACK) {
270                 w->color = RED;
271                 x = x->parent;
272             } else {
273                 if (w->right->color == BLACK) {
274                     w->left->color = BLACK;
275                     w->color = RED;
276                     rotateRight (rbt, w);
277                     w = x->parent->right;
278                 }
279                 w->color = x->parent->color;
280                 x->parent->color = BLACK;
281                 w->right->color = BLACK;
282                 rotateLeft (rbt, x->parent);
283                 x = rbt->root;
284             }
285         } else {
286             NodeType *w = x->parent->left;
287             if (w->color == RED) {
288                 w->color = BLACK;
289                 x->parent->color = RED;
290                 rotateRight (rbt, x->parent);
291                 w = x->parent->left;
292             }
293             if (w->right->color == BLACK && w->left->color == BLACK) {
294                 w->color = RED;
295                 x = x->parent;
296             } else {
297                 if (w->left->color == BLACK) {
298                     w->right->color = BLACK;
299                     w->color = RED;
300                     rotateLeft (rbt, w);
301                     w = x->parent->left;
302                 }
303                 w->color = x->parent->color;
304                 x->parent->color = BLACK;
305                 w->left->color = BLACK;
306                 rotateRight (rbt, x->parent);
307                 x = rbt->root;
308             }
309         }
310     }
311     x->color = BLACK;
312 }
313 
rbtErase(RbtHandle h,RbtIterator i)314 RbtStatus rbtErase(RbtHandle h, RbtIterator i) {
315     NodeType *x, *y;
316     RbtType *rbt = h;
317     NodeType *z = i;
318 
319     if (z->left == SENTINEL || z->right == SENTINEL) {
320         // y has a SENTINEL node as a child
321         y = z;
322     } else {
323         // find tree successor with a SENTINEL node as a child
324         y = z->right;
325         while (y->left != SENTINEL) y = y->left;
326     }
327 
328     // x is y's only child
329     if (y->left != SENTINEL)
330         x = y->left;
331     else
332         x = y->right;
333 
334     // remove y from the parent chain
335     x->parent = y->parent;
336     if (y->parent)
337         if (y == y->parent->left)
338             y->parent->left = x;
339         else
340             y->parent->right = x;
341     else
342         rbt->root = x;
343 
344     if (y != z) {
345         z->key = y->key;
346         z->val = y->val;
347     }
348 
349 
350     if (y->color == BLACK)
351         deleteFixup (rbt, x);
352 
353     free (y);
354 
355     return RBT_STATUS_OK;
356 }
357 
rbtNext(RbtHandle h,RbtIterator it)358 RbtIterator rbtNext(RbtHandle h, RbtIterator it) {
359     RbtType *rbt = h;
360     NodeType *i = it;
361 
362     if (i->right != SENTINEL) {
363         // go right 1, then left to the end
364         for (i = i->right; i->left != SENTINEL; i = i->left);
365     } else {
366         // while you're the right child, chain up parent link
367         NodeType *p = i->parent;
368         while (p && i == p->right) {
369             i = p;
370             p = p->parent;
371         }
372 
373         // return the "inorder" node
374         i = p;
375     }
376     return i != SENTINEL ? i : NULL;
377 }
378 
rbtBegin(RbtHandle h)379 RbtIterator rbtBegin(RbtHandle h) {
380     RbtType *rbt = h;
381 
382     // return pointer to first value
383     NodeType *i;
384     for (i = rbt->root; i->left != SENTINEL; i = i->left);
385     return i != SENTINEL ? i : NULL;
386 }
387 
rbtEnd(RbtHandle h)388 RbtIterator rbtEnd(RbtHandle h) {
389    // return pointer to one past last value
390    return NULL;
391 }
392 
rbtKeyValue(RbtHandle h,RbtIterator it,void ** key,void ** val)393 void rbtKeyValue(RbtHandle h, RbtIterator it, void **key, void **val) {
394     NodeType *i = it;
395 
396     *key = i->key;
397     *val = i->val;
398 }
399 
rbtFindLeftmost(RbtHandle h,void * key,int (* compare)(void * a,void * b))400 void *rbtFindLeftmost(RbtHandle h, void *key, int(*compare)(void *a, void *b))
401 {
402 	RbtType *rbt = h;
403 	NodeType *current = rbt->root;
404 	NodeType *found = NULL;
405 
406 	while (current != SENTINEL) {
407 		int rc = compare(key, current->key);
408 
409 		if (rc == 0) {
410 			found = current;
411 			current = current->left;
412 		} else if (found) {
413 			if (rc == 1)
414 				current = current->right;
415 			else
416 				return found;
417 		} else {
418 			current = (rc < 0) ? current->left : current->right;
419 		}
420 	}
421 
422 	return found;
423 }
424 
rbtFind(RbtHandle h,void * key)425 void *rbtFind(RbtHandle h, void *key) {
426     RbtType *rbt = h;
427 
428     NodeType *current;
429     current = rbt->root;
430     while(current != SENTINEL) {
431         int rc = rbt->compare(key, current->key);
432         if (rc == 0) return current;
433         current = (rc < 0) ? current->left : current->right;
434     }
435     return NULL;
436 }
437 
rbtTraversal(RbtHandle h,RbtIterator it,void * handler_arg,void (* handler)(void * arg,RbtIterator it))438 void rbtTraversal(RbtHandle h, RbtIterator it, void *handler_arg,
439           void(*handler)(void *arg, RbtIterator it)) {
440     RbtType *rbt = h;
441     NodeType *root = it;
442 
443     // apply handler for:
444     // -o the root of the tree/subtree
445     handler(handler_arg, it);
446     // - the left subtree
447     if (root->left != SENTINEL)
448         rbtTraversal(h, root->left, handler_arg, handler);
449     // - the right subtree
450     if (root->right != SENTINEL)
451         rbtTraversal(h, root->right, handler_arg, handler);
452 }
453 
rbtRoot(RbtHandle h)454 void *rbtRoot(RbtHandle h) {
455     RbtType *rbt = h;
456     return rbt->root;
457 }
458