10 //////////////////////
12 typedef int KeyType; // type of key
14 typedef struct { // value related to key
18 // how to compare keys
19 #define compLT(a,b) (a < b)
20 #define compEQ(a,b) (a == b)
22 /////////////////////////////////////
23 // implementation independent code //
24 /////////////////////////////////////
28 RBT_STATUS_MEM_EXHAUSTED,
29 RBT_STATUS_DUPLICATE_KEY,
30 RBT_STATUS_KEY_NOT_FOUND
33 typedef enum { BLACK, RED } nodeColor;
35 typedef struct NodeTag {
36 struct NodeTag *left; // left child
37 struct NodeTag *right; // right child
38 struct NodeTag *parent; // parent
39 nodeColor color; // node color (BLACK, RED)
40 KeyType key; // key used for searching
41 ValType val; // data related to key
44 #define SENTINEL &sentinel // all leafs are sentinels
45 static NodeType sentinel = { SENTINEL, SENTINEL, 0, BLACK, 0};
47 static NodeType *root = SENTINEL; // root of red-black tree
49 static void rotateLeft(NodeType *x) {
51 // rotate node x to left
53 NodeType *y = x->right;
55 // establish x->right link
57 if (y->left != SENTINEL) y->left->parent = x;
59 // establish y->parent link
60 if (y != SENTINEL) y->parent = x->parent;
62 if (x == x->parent->left)
72 if (x != SENTINEL) x->parent = y;
75 static void rotateRight(NodeType *x) {
77 // rotate node x to right
79 NodeType *y = x->left;
81 // establish x->left link
83 if (y->right != SENTINEL) y->right->parent = x;
85 // establish y->parent link
86 if (y != SENTINEL) y->parent = x->parent;
88 if (x == x->parent->right)
98 if (x != SENTINEL) x->parent = y;
101 static void insertFixup(NodeType *x) {
103 // maintain red-black tree balance
104 // after inserting node x
106 // check red-black properties
107 while (x != root && x->parent->color == RED) {
108 // we have a violation
109 if (x->parent == x->parent->parent->left) {
110 NodeType *y = x->parent->parent->right;
111 if (y->color == RED) {
114 x->parent->color = BLACK;
116 x->parent->parent->color = RED;
117 x = x->parent->parent;
121 if (x == x->parent->right) {
122 // make x a left child
127 // recolor and rotate
128 x->parent->color = BLACK;
129 x->parent->parent->color = RED;
130 rotateRight(x->parent->parent);
134 // mirror image of above code
135 NodeType *y = x->parent->parent->left;
136 if (y->color == RED) {
139 x->parent->color = BLACK;
141 x->parent->parent->color = RED;
142 x = x->parent->parent;
146 if (x == x->parent->left) {
150 x->parent->color = BLACK;
151 x->parent->parent->color = RED;
152 rotateLeft(x->parent->parent);
159 // insert new node (no duplicates allowed)
160 RbtStatus rbtInsert(KeyType key, ValType val) {
161 NodeType *current, *parent, *x;
163 // allocate node for data and insert in tree
165 // find future parent
168 while (current != SENTINEL) {
169 if (compEQ(key, current->key))
170 return RBT_STATUS_DUPLICATE_KEY;
172 current = compLT(key, current->key) ?
173 current->left : current->right;
177 if ((x = malloc (sizeof(*x))) == 0)
178 return RBT_STATUS_MEM_EXHAUSTED;
186 // insert node in tree
188 if(compLT(key, parent->key))
198 return RBT_STATUS_OK;
201 static void deleteFixup(NodeType *x) {
203 // maintain red-black tree balance
204 // after deleting node x
206 while (x != root && x->color == BLACK) {
207 if (x == x->parent->left) {
208 NodeType *w = x->parent->right;
209 if (w->color == RED) {
211 x->parent->color = RED;
212 rotateLeft (x->parent);
213 w = x->parent->right;
215 if (w->left->color == BLACK && w->right->color == BLACK) {
219 if (w->right->color == BLACK) {
220 w->left->color = BLACK;
223 w = x->parent->right;
225 w->color = x->parent->color;
226 x->parent->color = BLACK;
227 w->right->color = BLACK;
228 rotateLeft (x->parent);
232 NodeType *w = x->parent->left;
233 if (w->color == RED) {
235 x->parent->color = RED;
236 rotateRight (x->parent);
239 if (w->right->color == BLACK && w->left->color == BLACK) {
243 if (w->left->color == BLACK) {
244 w->right->color = BLACK;
249 w->color = x->parent->color;
250 x->parent->color = BLACK;
251 w->left->color = BLACK;
252 rotateRight (x->parent);
261 RbtStatus rbtErase(NodeType * z) {
264 if (z->left == SENTINEL || z->right == SENTINEL) {
265 // y has a SENTINEL node as a child
268 // find tree successor with a SENTINEL node as a child
270 while (y->left != SENTINEL) y = y->left;
273 // x is y's only child
274 if (y->left != SENTINEL)
279 // remove y from the parent chain
280 x->parent = y->parent;
282 if (y == y->parent->left)
285 y->parent->right = x;
295 if (y->color == BLACK)
300 return RBT_STATUS_OK;
304 NodeType *rbtFind(KeyType key) {
307 while(current != SENTINEL) {
308 if(compEQ(key, current->key)) {
311 current = compLT (key, current->key) ?
312 current->left : current->right;
318 // in-order walk of tree
319 void rbtInorder(NodeType *p, void (callback)(NodeType *)) {
320 if (p == SENTINEL) return;
321 rbtInorder(p->left, callback);
323 rbtInorder(p->right, callback);
326 // delete nodes depth-first
327 void rbtDelete(NodeType *p) {
328 if (p == SENTINEL) return;
334 void displayNode(NodeType *p) {
335 printf("%d %d\n", p->key, p->val.stuff);
338 int main(int argc, char **argv) {
346 // process 2000 records
350 maxnum = atoi(argv[1]);
352 printf("maxnum = %d\n", maxnum);
353 for (ct = maxnum; ct; ct--) {
354 key = rand() % 90 + 1;
355 if ((p = rbtFind(key)) != NULL) {
356 if (p->val.stuff != 10*key) printf("fail val\n");
357 status = rbtErase(p);
358 if (status) printf("fail: status = %d\n", status);
362 status = rbtInsert(key, val);
363 if (status) printf("fail: status = %d\n", status);
367 // output nodes in order
368 rbtInorder(root, displayNode);