1 // reentrant red-black tree
6 typedef enum { BLACK, RED } NodeColor;
8 typedef struct NodeTag {
9 struct NodeTag *left; // left child
10 struct NodeTag *right; // right child
11 struct NodeTag *parent; // parent
12 NodeColor color; // node color (BLACK, RED)
13 void *key; // key used for searching
14 void *val; // user data
17 typedef struct RbtTag {
18 NodeType *root; // root of red-black tree
20 int (*compare)(void *a, void *b); // compare keys
23 // all leafs are sentinels
24 #define SENTINEL &rbt->sentinel
26 RbtHandle rbtNew(int(*rbtCompare)(void *a, void *b)) {
29 if ((rbt = (RbtType *)malloc(sizeof(RbtType))) == NULL) {
33 rbt->compare = rbtCompare;
35 rbt->sentinel.left = SENTINEL;
36 rbt->sentinel.right = SENTINEL;
37 rbt->sentinel.parent = NULL;
38 rbt->sentinel.color = BLACK;
39 rbt->sentinel.key = NULL;
40 rbt->sentinel.val = NULL;
45 static void deleteTree(RbtHandle h, NodeType *p) {
48 // erase nodes depth-first
49 if (p == SENTINEL) return;
50 deleteTree(h, p->left);
51 deleteTree(h, p->right);
55 void rbtDelete(RbtHandle h) {
58 deleteTree(h, rbt->root);
62 static void rotateLeft(RbtType *rbt, NodeType *x) {
64 // rotate node x to left
66 NodeType *y = x->right;
68 // establish x->right link
70 if (y->left != SENTINEL) y->left->parent = x;
72 // establish y->parent link
73 if (y != SENTINEL) y->parent = x->parent;
75 if (x == x->parent->left)
85 if (x != SENTINEL) x->parent = y;
88 static void rotateRight(RbtType *rbt, NodeType *x) {
90 // rotate node x to right
92 NodeType *y = x->left;
94 // establish x->left link
96 if (y->right != SENTINEL) y->right->parent = x;
98 // establish y->parent link
99 if (y != SENTINEL) y->parent = x->parent;
101 if (x == x->parent->right)
102 x->parent->right = y;
111 if (x != SENTINEL) x->parent = y;
114 static void insertFixup(RbtType *rbt, NodeType *x) {
116 // maintain red-black tree balance after inserting node x
118 // check red-black properties
119 while (x != rbt->root && x->parent->color == RED) {
120 // we have a violation
121 if (x->parent == x->parent->parent->left) {
122 NodeType *y = x->parent->parent->right;
123 if (y->color == RED) {
126 x->parent->color = BLACK;
128 x->parent->parent->color = RED;
129 x = x->parent->parent;
133 if (x == x->parent->right) {
134 // make x a left child
139 // recolor and rotate
140 x->parent->color = BLACK;
141 x->parent->parent->color = RED;
142 rotateRight(rbt, x->parent->parent);
146 // mirror image of above code
147 NodeType *y = x->parent->parent->left;
148 if (y->color == RED) {
151 x->parent->color = BLACK;
153 x->parent->parent->color = RED;
154 x = x->parent->parent;
158 if (x == x->parent->left) {
162 x->parent->color = BLACK;
163 x->parent->parent->color = RED;
164 rotateLeft(rbt, x->parent->parent);
168 rbt->root->color = BLACK;
171 RbtStatus rbtInsert(RbtHandle h, void *key, void *val) {
172 NodeType *current, *parent, *x;
175 // allocate node for data and insert in tree
177 // find future parent
180 while (current != SENTINEL) {
181 int rc = rbt->compare(key, current->key);
183 return RBT_STATUS_DUPLICATE_KEY;
185 current = (rc < 0) ? current->left : current->right;
189 if ((x = malloc (sizeof(*x))) == 0)
190 return RBT_STATUS_MEM_EXHAUSTED;
198 // insert node in tree
200 if(rbt->compare(key, parent->key) < 0)
210 return RBT_STATUS_OK;
213 void deleteFixup(RbtType *rbt, NodeType *x) {
215 // maintain red-black tree balance after deleting node x
217 while (x != rbt->root && x->color == BLACK) {
218 if (x == x->parent->left) {
219 NodeType *w = x->parent->right;
220 if (w->color == RED) {
222 x->parent->color = RED;
223 rotateLeft (rbt, x->parent);
224 w = x->parent->right;
226 if (w->left->color == BLACK && w->right->color == BLACK) {
230 if (w->right->color == BLACK) {
231 w->left->color = BLACK;
233 rotateRight (rbt, w);
234 w = x->parent->right;
236 w->color = x->parent->color;
237 x->parent->color = BLACK;
238 w->right->color = BLACK;
239 rotateLeft (rbt, x->parent);
243 NodeType *w = x->parent->left;
244 if (w->color == RED) {
246 x->parent->color = RED;
247 rotateRight (rbt, x->parent);
250 if (w->right->color == BLACK && w->left->color == BLACK) {
254 if (w->left->color == BLACK) {
255 w->right->color = BLACK;
260 w->color = x->parent->color;
261 x->parent->color = BLACK;
262 w->left->color = BLACK;
263 rotateRight (rbt, x->parent);
271 RbtStatus rbtErase(RbtHandle h, RbtIterator i) {
276 if (z->left == SENTINEL || z->right == SENTINEL) {
277 // y has a SENTINEL node as a child
280 // find tree successor with a SENTINEL node as a child
282 while (y->left != SENTINEL) y = y->left;
285 // x is y's only child
286 if (y->left != SENTINEL)
291 // remove y from the parent chain
292 x->parent = y->parent;
294 if (y == y->parent->left)
297 y->parent->right = x;
307 if (y->color == BLACK)
308 deleteFixup (rbt, x);
312 return RBT_STATUS_OK;
315 RbtIterator rbtNext(RbtHandle h, RbtIterator it) {
319 if (i->right != SENTINEL) {
320 // go right 1, then left to the end
321 for (i = i->right; i->left != SENTINEL; i = i->left);
323 // while you're the right child, chain up parent link
324 NodeType *p = i->parent;
325 while (p && i == p->right) {
330 // return the "inorder" node
333 return i != SENTINEL ? i : NULL;
336 RbtIterator rbtBegin(RbtHandle h) {
339 // return pointer to first value
341 for (i = rbt->root; i->left != SENTINEL; i = i->left);
342 return i != SENTINEL ? i : NULL;
345 RbtIterator rbtEnd(RbtHandle h) {
346 // return pointer to one past last value
350 void rbtKeyValue(RbtHandle h, RbtIterator it, void **key, void **val) {
358 void *rbtFind(RbtHandle h, void *key) {
363 while(current != SENTINEL) {
364 int rc = rbt->compare(key, current->key);
365 if (rc == 0) return current;
366 current = (rc < 0) ? current->left : current->right;