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