aboutsummaryrefslogtreecommitdiff
path: root/rb.c
diff options
context:
space:
mode:
authorThomas Schmucker <ts@its1.de>2020-07-22 17:30:45 +0200
committerThomas Schmucker <ts@its1.de>2020-07-22 17:30:45 +0200
commitac55496d881e0a17b3eff85f1faae5aafbc53b50 (patch)
tree65b954e994d7bbfc76bc959876e28f7ea9fa708c /rb.c
downloaddata-structures-ac55496d881e0a17b3eff85f1faae5aafbc53b50.tar.gz
data-structures-ac55496d881e0a17b3eff85f1faae5aafbc53b50.tar.bz2
data-structures-ac55496d881e0a17b3eff85f1faae5aafbc53b50.zip
erster Commit
Diffstat (limited to 'rb.c')
-rw-r--r--rb.c661
1 files changed, 661 insertions, 0 deletions
diff --git a/rb.c b/rb.c
new file mode 100644
index 0000000..c95ab83
--- /dev/null
+++ b/rb.c
@@ -0,0 +1,661 @@
1#include <stdio.h>
2#include <stdlib.h>
3#include <time.h>
4#include "util.h"
5
6typedef int T;
7
8#if 0
9struct rbtree {
10 T data;
11 enum { RED, BLACK } color;
12 struct rbtree *left, *right, *p;
13};
14
15struct rbtree *
16rb_alloc(T data)
17{
18 struct rbtree *node = malloc(sizeof *node);
19 if ( node )
20 {
21 node->data = data;
22 node->left = NULL;
23 node->right = NULL;
24 node->p = NULL;
25 }
26 return node;
27}
28
29void
30rb_left_rotate(struct rbtree **root, struct rbtree *x)
31{
32 struct rbtree *y = x->right;
33 x->right = y->left;
34 if ( y->left )
35 y->left->p = x;
36
37 y->p = x->p;
38 if ( x->p == NULL )
39 *root = y;
40 else if ( x == x->p->left )
41 x->p->left = y;
42 else
43 x->p->right = y;
44
45 y->left = x;
46 x->p = y;
47}
48
49void
50rb_right_rotate(struct rbtree **root, struct rbtree *y)
51{
52 struct rbtree *x = y->left;
53 y->left = x->right;
54 if ( x->right )
55 x->right->p = y;
56
57 x->p = y->p;
58 if ( y->p == NULL )
59 *root = x;
60 else if ( y == y->p->left )
61 y->p->left = x;
62 else
63 y->p->right = x;
64
65 x->right = y;
66 y->p = x;
67}
68
69void
70rb_insert_fixup(struct rbtree **root, struct rbtree **z)
71{
72 struct rbtree *y;
73
74 while ( z->p->color == RED ) {
75 if ( z->p == z->p->p->left ) {
76 y = z->p->p->right;
77 if ( y->color == RED ) {
78 z->p->color = BLACK;
79 y->color = BLACK;
80 z->p->p->color = RED;
81 z = z->p->p;
82 }
83 else {
84 if ( z == z->p->right ) {
85 z = z->p;
86 rb_left_rotate(root, z);
87 }
88 z->p->color = BLACK;
89 z->p->p->color = RED;
90 rb_right_rotate(root, z->p->p);
91 }
92 }
93 else {
94 y = z->p->p->left;
95 if ( y->color == RED ) {
96 z->p->color = BLACK;
97 y->color = BLACK;
98 z->p->p->color = RED;
99 z = z->p->p;
100 }
101 else {
102 if ( z == z->p->left ) {
103 z = z->p;
104 rb_right_rotate(root, z);
105 }
106 z->p->color = BLACK;
107 z->p->p->color = RED;
108 rb_left_rotate(root, z->p->p);
109 }
110 }
111 }
112
113 (*root)->color = BLACK;
114}
115
116void
117rb_insert_node(struct rbtree **root, T data)
118{
119 struct rbtree *z = rb_alloc(data);
120
121 if ( *root == NULL ) {
122 z->color = BLACK;
123 *root = z;
124 }
125 else {
126 struct rbtree *y = NULL;
127 struct rbtree *x = *root;
128
129 while ( x ) {
130 y = x;
131 if ( z->data < x->data )
132 x = x->left;
133 else
134 x = x->right;
135 }
136 z->p = y;
137
138 if ( y == NULL ) // kann entfallen!
139 *root = z;
140 else if ( z->data < y->data )
141 y->left = z;
142 else
143 y->right = z;
144
145 z->left = NULL; // kann entfallen!
146 z->right = NULL; // kann entfallen!
147 z->color = RED;
148
149 rb_insert_fixup(root, &z);
150 }
151}
152
153#endif
154
155
156
157/* The authors of this work have released all rights to it and placed it
158in the public domain under the Creative Commons CC0 1.0 waiver
159(http://creativecommons.org/publicdomain/zero/1.0/).
160
161THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
162EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
163MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
164IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
165CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
166TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
167SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
168
169Retrieved from: http://en.literateprograms.org/Red-black_tree_(C)?oldid=19567
170*/
171
172enum rbtree_node_color { RED, BLACK };
173
174typedef struct rbtree_node_t {
175void* key;
176void* value;
177struct rbtree_node_t* left;
178struct rbtree_node_t* right;
179struct rbtree_node_t* parent;
180enum rbtree_node_color color;
181} *rbtree_node;
182
183typedef struct rbtree_t {
184rbtree_node root;
185} *rbtree;
186
187typedef int (*compare_func)(void* left, void* right);
188
189rbtree rbtree_create();
190void* rbtree_lookup(rbtree t, void* key, compare_func compare);
191void rbtree_insert(rbtree t, void* key, void* value, compare_func compare);
192void rbtree_delete(rbtree t, void* key, compare_func compare);
193
194
195#include <assert.h>
196#include <stdlib.h>
197
198typedef rbtree_node node;
199typedef enum rbtree_node_color color;
200
201static node grandparent(node n);
202static node sibling(node n);
203static node uncle(node n);
204static void verify_properties(rbtree t);
205static void verify_property_1(node root);
206static void verify_property_2(node root);
207static color node_color(node n);
208static void verify_property_4(node root);
209static void verify_property_5(node root);
210static void verify_property_5_helper(node n, int black_count, int* black_count_path);
211
212static node new_node(void* key, void* value, color node_color, node left, node right);
213static node lookup_node(rbtree t, void* key, compare_func compare);
214static void rotate_left(rbtree t, node n);
215static void rotate_right(rbtree t, node n);
216
217static void replace_node(rbtree t, node oldn, node newn);
218static void insert_case1(rbtree t, node n);
219static void insert_case2(rbtree t, node n);
220static void insert_case3(rbtree t, node n);
221static void insert_case4(rbtree t, node n);
222static void insert_case5(rbtree t, node n);
223static node maximum_node(node root);
224static void delete_case1(rbtree t, node n);
225static void delete_case2(rbtree t, node n);
226static void delete_case3(rbtree t, node n);
227static void delete_case4(rbtree t, node n);
228static void delete_case5(rbtree t, node n);
229static void delete_case6(rbtree t, node n);
230
231node grandparent(node n) {
232 assert (n != NULL);
233 assert (n->parent != NULL); /* Not the root node */
234 assert (n->parent->parent != NULL); /* Not child of root */
235 return n->parent->parent;
236}
237node sibling(node n) {
238 assert (n != NULL);
239 assert (n->parent != NULL); /* Root node has no sibling */
240 if (n == n->parent->left)
241 return n->parent->right;
242 else
243 return n->parent->left;
244}
245node uncle(node n) {
246 assert (n != NULL);
247 assert (n->parent != NULL); /* Root node has no uncle */
248 assert (n->parent->parent != NULL); /* Children of root have no uncle */
249 return sibling(n->parent);
250}
251void verify_properties(rbtree t) {
252#ifdef VERIFY_RBTREE
253 verify_property_1(t->root);
254 verify_property_2(t->root);
255 /* Property 3 is implicit */
256 verify_property_4(t->root);
257 verify_property_5(t->root);
258#endif
259}
260void verify_property_1(node n) {
261 assert(node_color(n) == RED || node_color(n) == BLACK);
262 if (n == NULL) return;
263 verify_property_1(n->left);
264 verify_property_1(n->right);
265}
266void verify_property_2(node root) {
267 assert(node_color(root) == BLACK);
268}
269color node_color(node n) {
270 return n == NULL ? BLACK : n->color;
271}
272void verify_property_4(node n) {
273 if (node_color(n) == RED) {
274 assert (node_color(n->left) == BLACK);
275 assert (node_color(n->right) == BLACK);
276 assert (node_color(n->parent) == BLACK);
277 }
278 if (n == NULL) return;
279 verify_property_4(n->left);
280 verify_property_4(n->right);
281}
282void verify_property_5(node root) {
283 int black_count_path = -1;
284 verify_property_5_helper(root, 0, &black_count_path);
285}
286
287void verify_property_5_helper(node n, int black_count, int* path_black_count) {
288 if (node_color(n) == BLACK) {
289 black_count++;
290 }
291 if (n == NULL) {
292 if (*path_black_count == -1) {
293 *path_black_count = black_count;
294 } else {
295 assert (black_count == *path_black_count);
296 }
297 return;
298 }
299 verify_property_5_helper(n->left, black_count, path_black_count);
300 verify_property_5_helper(n->right, black_count, path_black_count);
301}
302rbtree rbtree_create() {
303 rbtree t = malloc(sizeof(struct rbtree_t));
304 t->root = NULL;
305 verify_properties(t);
306 return t;
307}
308node new_node(void* key, void* value, color node_color, node left, node right) {
309 node result = malloc(sizeof(struct rbtree_node_t));
310 result->key = key;
311 result->value = value;
312 result->color = node_color;
313 result->left = left;
314 result->right = right;
315 if (left != NULL) left->parent = result;
316 if (right != NULL) right->parent = result;
317 result->parent = NULL;
318 return result;
319}
320node lookup_node(rbtree t, void* key, compare_func compare) {
321 node n = t->root;
322 while (n != NULL) {
323 int comp_result = compare(key, n->key);
324 if (comp_result == 0) {
325 return n;
326 } else if (comp_result < 0) {
327 n = n->left;
328 } else {
329 assert(comp_result > 0);
330 n = n->right;
331 }
332 }
333 return n;
334}
335void* rbtree_lookup(rbtree t, void* key, compare_func compare) {
336 node n = lookup_node(t, key, compare);
337 return n == NULL ? NULL : n->value;
338}
339void rotate_left(rbtree t, node n) {
340 node r = n->right;
341 replace_node(t, n, r);
342 n->right = r->left;
343 if (r->left != NULL) {
344 r->left->parent = n;
345 }
346 r->left = n;
347 n->parent = r;
348}
349
350void rotate_right(rbtree t, node n) {
351 node L = n->left;
352 replace_node(t, n, L);
353 n->left = L->right;
354 if (L->right != NULL) {
355 L->right->parent = n;
356 }
357 L->right = n;
358 n->parent = L;
359}
360void replace_node(rbtree t, node oldn, node newn) {
361 if (oldn->parent == NULL) {
362 t->root = newn;
363 } else {
364 if (oldn == oldn->parent->left)
365 oldn->parent->left = newn;
366 else
367 oldn->parent->right = newn;
368 }
369 if (newn != NULL) {
370 newn->parent = oldn->parent;
371 }
372}
373void rbtree_insert(rbtree t, void* key, void* value, compare_func compare) {
374 node inserted_node = new_node(key, value, RED, NULL, NULL);
375 if (t->root == NULL) {
376 t->root = inserted_node;
377 } else {
378 node n = t->root;
379 while (1) {
380 int comp_result = compare(key, n->key);
381 if (comp_result == 0) {
382 n->value = value;
383 return;
384 } else if (comp_result < 0) {
385 if (n->left == NULL) {
386 n->left = inserted_node;
387 break;
388 } else {
389 n = n->left;
390 }
391 } else {
392 assert (comp_result > 0);
393 if (n->right == NULL) {
394 n->right = inserted_node;
395 break;
396 } else {
397 n = n->right;
398 }
399 }
400 }
401 inserted_node->parent = n;
402 }
403 insert_case1(t, inserted_node);
404 verify_properties(t);
405}
406void insert_case1(rbtree t, node n) {
407 if (n->parent == NULL)
408 n->color = BLACK;
409 else
410 insert_case2(t, n);
411}
412void insert_case2(rbtree t, node n) {
413 if (node_color(n->parent) == BLACK)
414 return; /* Tree is still valid */
415 else
416 insert_case3(t, n);
417}
418void insert_case3(rbtree t, node n) {
419 if (node_color(uncle(n)) == RED) {
420 n->parent->color = BLACK;
421 uncle(n)->color = BLACK;
422 grandparent(n)->color = RED;
423 insert_case1(t, grandparent(n));
424 } else {
425 insert_case4(t, n);
426 }
427}
428void insert_case4(rbtree t, node n) {
429 if (n == n->parent->right && n->parent == grandparent(n)->left) {
430 rotate_left(t, n->parent);
431 n = n->left;
432 } else if (n == n->parent->left && n->parent == grandparent(n)->right) {
433 rotate_right(t, n->parent);
434 n = n->right;
435 }
436 insert_case5(t, n);
437}
438void insert_case5(rbtree t, node n) {
439 n->parent->color = BLACK;
440 grandparent(n)->color = RED;
441 if (n == n->parent->left && n->parent == grandparent(n)->left) {
442 rotate_right(t, grandparent(n));
443 } else {
444 assert (n == n->parent->right && n->parent == grandparent(n)->right);
445 rotate_left(t, grandparent(n));
446 }
447}
448void rbtree_delete(rbtree t, void* key, compare_func compare) {
449 node child;
450 node n = lookup_node(t, key, compare);
451 if (n == NULL) return; /* Key not found, do nothing */
452 if (n->left != NULL && n->right != NULL) {
453 /* Copy key/value from predecessor and then delete it instead */
454 node pred = maximum_node(n->left);
455 n->key = pred->key;
456 n->value = pred->value;
457 n = pred;
458 }
459
460 assert(n->left == NULL || n->right == NULL);
461 child = n->right == NULL ? n->left : n->right;
462 if (node_color(n) == BLACK) {
463 n->color = node_color(child);
464 delete_case1(t, n);
465 }
466 replace_node(t, n, child);
467 if (n->parent == NULL && child != NULL) // root should be black
468 child->color = BLACK;
469 free(n);
470
471 verify_properties(t);
472}
473static node maximum_node(node n) {
474 assert (n != NULL);
475 while (n->right != NULL) {
476 n = n->right;
477 }
478 return n;
479}
480void delete_case1(rbtree t, node n) {
481 if (n->parent == NULL)
482 return;
483 else
484 delete_case2(t, n);
485}
486void delete_case2(rbtree t, node n) {
487 if (node_color(sibling(n)) == RED) {
488 n->parent->color = RED;
489 sibling(n)->color = BLACK;
490 if (n == n->parent->left)
491 rotate_left(t, n->parent);
492 else
493 rotate_right(t, n->parent);
494 }
495 delete_case3(t, n);
496}
497void delete_case3(rbtree t, node n) {
498 if (node_color(n->parent) == BLACK &&
499 node_color(sibling(n)) == BLACK &&
500 node_color(sibling(n)->left) == BLACK &&
501 node_color(sibling(n)->right) == BLACK)
502 {
503 sibling(n)->color = RED;
504 delete_case1(t, n->parent);
505 }
506 else
507 delete_case4(t, n);
508}
509void delete_case4(rbtree t, node n) {
510 if (node_color(n->parent) == RED &&
511 node_color(sibling(n)) == BLACK &&
512 node_color(sibling(n)->left) == BLACK &&
513 node_color(sibling(n)->right) == BLACK)
514 {
515 sibling(n)->color = RED;
516 n->parent->color = BLACK;
517 }
518 else
519 delete_case5(t, n);
520}
521void delete_case5(rbtree t, node n) {
522 if (n == n->parent->left &&
523 node_color(sibling(n)) == BLACK &&
524 node_color(sibling(n)->left) == RED &&
525 node_color(sibling(n)->right) == BLACK)
526 {
527 sibling(n)->color = RED;
528 sibling(n)->left->color = BLACK;
529 rotate_right(t, sibling(n));
530 }
531 else if (n == n->parent->right &&
532 node_color(sibling(n)) == BLACK &&
533 node_color(sibling(n)->right) == RED &&
534 node_color(sibling(n)->left) == BLACK)
535 {
536 sibling(n)->color = RED;
537 sibling(n)->right->color = BLACK;
538 rotate_left(t, sibling(n));
539 }
540 delete_case6(t, n);
541}
542void delete_case6(rbtree t, node n) {
543 sibling(n)->color = node_color(n->parent);
544 n->parent->color = BLACK;
545 if (n == n->parent->left) {
546 assert (node_color(sibling(n)->right) == RED);
547 sibling(n)->right->color = BLACK;
548 rotate_left(t, n->parent);
549 }
550 else
551 {
552 assert (node_color(sibling(n)->left) == RED);
553 sibling(n)->left->color = BLACK;
554 rotate_right(t, n->parent);
555 }
556}
557
558
559
560/* The authors of this work have released all rights to it and placed it
561in the public domain under the Creative Commons CC0 1.0 waiver
562(http://creativecommons.org/publicdomain/zero/1.0/).
563
564THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
565EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
566MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
567IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
568CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
569TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
570SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
571
572Retrieved from: http://en.literateprograms.org/Red-black_tree_(C)?oldid=19567
573*/
574
575#include <stdio.h>
576#include <assert.h>
577#include <stdlib.h> /* rand() */
578
579static int compare_int(void* left, void* right);
580static void print_tree(rbtree t);
581static void print_tree_helper(rbtree_node n, int indent);
582
583int compare_int(void* leftp, void* rightp) {
584 int left = (int)leftp;
585 int right = (int)rightp;
586 if (left < right)
587 return -1;
588 else if (left > right)
589 return 1;
590 else {
591 assert (left == right);
592 return 0;
593 }
594}
595
596#define INDENT_STEP 4
597
598void print_tree_helper(rbtree_node n, int indent);
599
600void print_tree(rbtree t) {
601 print_tree_helper(t->root, 0);
602 puts("");
603}
604
605void print_tree_helper(rbtree_node n, int indent) {
606 int i;
607 if (n == NULL) {
608 fputs("<empty tree>", stdout);
609 return;
610 }
611 if (n->right != NULL) {
612 print_tree_helper(n->right, indent + INDENT_STEP);
613 }
614 for(i=0; i<indent; i++)
615 fputs(" ", stdout);
616 if (n->color == BLACK)
617 printf("%d\n", (int)n->key);
618 else
619 printf("<%d>\n", (int)n->key);
620 if (n->left != NULL) {
621 print_tree_helper(n->left, indent + INDENT_STEP);
622 }
623}
624
625int main() {
626 int i;
627 rbtree t = rbtree_create();
628 print_tree(t);
629
630 for(i=0; i<5000; i++) {
631 long x = rand() % 10000;
632 long y = rand() % 10000;
633#ifdef TRACE
634 print_tree(t);
635 printf("Inserting %d -> %d\n\n", x, y);
636#endif
637 rbtree_insert(t, (void*)x, (void*)y, compare_int);
638 assert(rbtree_lookup(t, (void*)x, compare_int) == (void*)y);
639 }
640 for(i=0; i<60000; i++) {
641 long x = rand() % 10000;
642#ifdef TRACE
643 print_tree(t);
644 printf("Deleting key %d\n\n", x);
645#endif
646 rbtree_delete(t, (void*)x, compare_int);
647 }
648 return 0;
649}
650
651#if 0
652int main__(void)
653{
654 struct rbtree *tree = NULL;
655
656 srand(time(NULL));
657 for ( int i = 0; i != 10; ++i )
658 rb_insert_node(&tree, rand());
659
660}
661#endif