Releasing version 3-2014010504
[notion/jeffpc.git] / libtu / rb.c
blob2e5006a1b56e13cf7d1b5efbee7f295630faba6b
1 /*
2 Generic C code for red-black trees.
3 Copyright (C) 2000 James S. Plank,
4 2004 Tuomo Valkonen.
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with this library; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
20 /* Revision 1.2. Jim Plank */
22 /* Original code by Jim Plank (plank@cs.utk.edu) */
23 /* modified for THINK C 6.0 for Macintosh by Chris Bartley */
25 #include <string.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <ctype.h>
29 #include "rb.h"
31 static void mk_new_int(Rb_node l, Rb_node r, Rb_node p, int il);
32 static Rb_node lprev(Rb_node n);
33 static Rb_node rprev(Rb_node n);
34 static void recolor(Rb_node n);
35 static void single_rotate(Rb_node y, int l);
36 static void rb_print_tree(Rb_node t, int level);
37 static void rb_iprint_tree(Rb_node t, int level);
39 /* Gcc complains if non-char* pointer is passed to printf %p */
40 #define DONT_COMPLAIN (char*)
42 #define isred(n) (n->s.red)
43 #define isblack(n) (!isred(n))
44 #define isleft(n) (n->s.left)
45 #define isright(n) (!isleft(n))
46 #define isint(n) (n->s.internal)
47 #define isext(n) (!isint(n))
48 #define ishead(n) (n->s.head)
49 #define isroot(n) (n->s.root)
50 #define setred(n) n->s.red = 1
51 #define setblack(n) n->s.red = 0
52 #define setleft(n) n->s.left = 1
53 #define setright(n) n->s.left = 0
54 #define sethead(n) n->s.head = 1
55 #define setroot(n) n->s.root = 1
56 #define setint(n) n->s.internal = 1
57 #define setext(n) n->s.internal = 0
58 #define setnormal(n) { n->s.root = 0; n ->s.head = 0; }
59 #define sibling(n) ((isleft(n)) ? n->p.parent->c.child.right \
60 : n->p.parent->c.child.left)
62 static void insert(Rb_node item, Rb_node list) /* Inserts to the end of a list */
64 Rb_node last_node;
66 last_node = list->c.list.blink;
68 list->c.list.blink = item;
69 last_node->c.list.flink = item;
70 item->c.list.blink = last_node;
71 item->c.list.flink = list;
74 static void delete_item(Rb_node item) /* Deletes an arbitrary iterm */
76 item->c.list.flink->c.list.blink = item->c.list.blink;
77 item->c.list.blink->c.list.flink = item->c.list.flink;
80 #define mk_new_ext(new, kkkey, vvval) {\
81 new = (Rb_node) malloc(sizeof(struct rb_node));\
82 if(new==NULL) return NULL;\
83 new->v.val = vvval;\
84 new->k.key = kkkey;\
85 setext(new);\
86 setblack(new);\
87 setnormal(new);\
90 static void mk_new_int(Rb_node l, Rb_node r, Rb_node p, int il)
92 Rb_node newnode;
94 newnode = (Rb_node) malloc(sizeof(struct rb_node));
95 setint(newnode);
96 setred(newnode);
97 setnormal(newnode);
98 newnode->c.child.left = l;
99 newnode->c.child.right = r;
100 newnode->p.parent = p;
101 newnode->k.lext = l;
102 newnode->v.rext = r;
103 l->p.parent = newnode;
104 r->p.parent = newnode;
105 setleft(l);
106 setright(r);
107 if (ishead(p)) {
108 p->p.root = newnode;
109 setroot(newnode);
110 } else if (il) {
111 setleft(newnode);
112 p->c.child.left = newnode;
113 } else {
114 setright(newnode);
115 p->c.child.right = newnode;
117 recolor(newnode);
121 Rb_node lprev(Rb_node n)
123 if (ishead(n)) return n;
124 while (!isroot(n)) {
125 if (isright(n)) return n->p.parent;
126 n = n->p.parent;
128 return n->p.parent;
131 Rb_node rprev(Rb_node n)
133 if (ishead(n)) return n;
134 while (!isroot(n)) {
135 if (isleft(n)) return n->p.parent;
136 n = n->p.parent;
138 return n->p.parent;
141 Rb_node make_rb()
143 Rb_node head;
145 head = (Rb_node) malloc (sizeof(struct rb_node));
146 if(head!=NULL){
147 head->c.list.flink = head;
148 head->c.list.blink = head;
149 head->p.root = head;
150 head->k.key = "";
151 sethead(head);
153 return head;
156 Rb_node rb_find_ikey_n(Rb_node n, int ikey, int *fnd)
158 *fnd = 0;
159 if (!ishead(n)) {
160 fprintf(stderr, "rb_find_ikey_n called on non-head %p\n",
161 DONT_COMPLAIN n);
162 exit(1);
164 if (n->p.root == n) return n;
165 if (ikey == n->c.list.blink->k.ikey) {
166 *fnd = 1;
167 return n->c.list.blink;
169 if (ikey > n->c.list.blink->k.ikey) return n;
170 else n = n->p.root;
171 while (1) {
172 if (isext(n)) return n;
173 if (ikey == n->k.lext->k.ikey) {
174 *fnd = 1;
175 return n->k.lext;
177 n = (ikey < n->k.lext->k.ikey) ? n->c.child.left : n->c.child.right;
181 Rb_node rb_find_ikey(Rb_node n, int ikey)
183 int fnd;
184 return rb_find_ikey_n(n, ikey, &fnd);
187 Rb_node rb_find_gkey_n(Rb_node n, const void *key, Rb_compfn *fxn, int *fnd)
189 int cmp;
191 *fnd = 0;
192 if (!ishead(n)) {
193 fprintf(stderr, "rb_find_gkey_n called on non-head %p\n",
194 DONT_COMPLAIN n);
195 exit(1);
197 if (n->p.root == n) return n;
198 cmp = (*fxn)(key, n->c.list.blink->k.key);
199 if (cmp == 0) {
200 *fnd = 1;
201 return n->c.list.blink;
203 if (cmp > 0) return n;
204 else n = n->p.root;
205 while (1) {
206 if (isext(n)) return n;
207 cmp = (*fxn)(key, n->k.lext->k.key);
208 if (cmp == 0) {
209 *fnd = 1;
210 return n->k.lext;
212 if (cmp < 0) n = n->c.child.left ; else n = n->c.child.right;
216 Rb_node rb_find_gkey(Rb_node n, const void *key, Rb_compfn *fxn)
218 int fnd;
219 return rb_find_gkey_n(n, key, fxn, &fnd);
222 Rb_node rb_find_key_n(Rb_node n, const char *key, int *fnd)
224 return rb_find_gkey_n(n, key, (Rb_compfn*)strcmp, fnd);
227 Rb_node rb_find_key(Rb_node n, const char *key)
229 int fnd;
230 return rb_find_gkey_n(n, key, (Rb_compfn*)strcmp, &fnd);
233 static int ptrcmp(const void *a, const void *b)
235 return (a<b ? -1 : ((a==b) ? 0 : 1));
238 Rb_node rb_find_pkey_n(Rb_node n, const void *key, int *fnd)
240 return rb_find_gkey_n(n, key, ptrcmp, fnd);
243 Rb_node rb_find_pkey(Rb_node n, const void *key)
245 int fnd;
246 return rb_find_gkey_n(n, key, ptrcmp, &fnd);
249 Rb_node rb_insert_b(Rb_node n, const void *key, void *val)
251 Rb_node newleft, newright, newnode, list, p;
253 if (ishead(n)) {
254 if (n->p.root == n) { /* Tree is empty */
255 mk_new_ext(newnode, key, val);
256 insert(newnode, n);
257 n->p.root = newnode;
258 newnode->p.parent = n;
259 setroot(newnode);
260 return newnode;
261 } else {
262 mk_new_ext(newright, key, val);
263 insert(newright, n);
264 newleft = newright->c.list.blink;
265 setnormal(newleft);
266 mk_new_int(newleft, newright, newleft->p.parent, isleft(newleft));
267 p = rprev(newright);
268 if (!ishead(p)) p->k.lext = newright;
269 return newright;
271 } else {
272 mk_new_ext(newleft, key, val);
273 insert(newleft, n);
274 setnormal(n);
275 mk_new_int(newleft, n, n->p.parent, isleft(n));
276 p = lprev(newleft);
277 if (!ishead(p)) p->v.rext = newleft;
278 return newleft;
282 static void recolor(Rb_node n)
284 Rb_node p, gp, s;
285 int done = 0;
287 while(!done) {
288 if (isroot(n)) {
289 setblack(n);
290 return;
293 p = n->p.parent;
295 if (isblack(p)) return;
297 if (isroot(p)) {
298 setblack(p);
299 return;
302 gp = p->p.parent;
303 s = sibling(p);
304 if (isred(s)) {
305 setblack(p);
306 setred(gp);
307 setblack(s);
308 n = gp;
309 } else {
310 done = 1;
313 /* p's sibling is black, p is red, gp is black */
315 if ((isleft(n) == 0) == (isleft(p) == 0)) {
316 single_rotate(gp, isleft(n));
317 setblack(p);
318 setred(gp);
319 } else {
320 single_rotate(p, isleft(n));
321 single_rotate(gp, isleft(n));
322 setblack(n);
323 setred(gp);
327 static void single_rotate(Rb_node y, int l)
329 int rl=0, ir=0;
330 Rb_node x=NULL, yp=NULL;
331 void *tmp=NULL;
333 ir = isroot(y);
334 yp = y->p.parent;
335 if (!ir) {
336 rl = isleft(y);
339 if (l) {
340 x = y->c.child.left;
341 y->c.child.left = x->c.child.right;
342 setleft(y->c.child.left);
343 y->c.child.left->p.parent = y;
344 x->c.child.right = y;
345 setright(y);
346 } else {
347 x = y->c.child.right;
348 y->c.child.right = x->c.child.left;
349 setright(y->c.child.right);
350 y->c.child.right->p.parent = y;
351 x->c.child.left = y;
352 setleft(y);
355 x->p.parent = yp;
356 y->p.parent = x;
357 if (ir) {
358 yp->p.root = x;
359 setnormal(y);
360 setroot(x);
361 } else {
362 if (rl) {
363 yp->c.child.left = x;
364 setleft(x);
365 } else {
366 yp->c.child.right = x;
367 setright(x);
372 void rb_delete_node(Rb_node n)
374 Rb_node s, p, gp;
375 char ir;
377 if (isint(n)) {
378 fprintf(stderr, "Cannot delete an internal node: %p\n", DONT_COMPLAIN n);
379 exit(1);
381 if (ishead(n)) {
382 fprintf(stderr, "Cannot delete the head of an rb_tree: %p\n", DONT_COMPLAIN n);
383 exit(1);
385 delete_item(n); /* Delete it from the list */
386 p = n->p.parent; /* The only node */
387 if (isroot(n)) {
388 p->p.root = p;
389 free(n);
390 return;
392 s = sibling(n); /* The only node after deletion */
393 if (isroot(p)) {
394 s->p.parent = p->p.parent;
395 s->p.parent->p.root = s;
396 setroot(s);
397 free(p);
398 free(n);
399 return;
401 gp = p->p.parent; /* Set parent to sibling */
402 s->p.parent = gp;
403 if (isleft(p)) {
404 gp->c.child.left = s;
405 setleft(s);
406 } else {
407 gp->c.child.right = s;
408 setright(s);
410 ir = isred(p);
411 free(p);
412 free(n);
414 if (isext(s)) { /* Update proper rext and lext values */
415 p = lprev(s);
416 if (!ishead(p)) p->v.rext = s;
417 p = rprev(s);
418 if (!ishead(p)) p->k.lext = s;
419 } else if (isblack(s)) {
420 fprintf(stderr, "DELETION PROB -- sib is black, internal\n");
421 exit(1);
422 } else {
423 p = lprev(s);
424 if (!ishead(p)) p->v.rext = s->c.child.left;
425 p = rprev(s);
426 if (!ishead(p)) p->k.lext = s->c.child.right;
427 setblack(s);
428 return;
431 if (ir) return;
433 /* Recolor */
435 n = s;
436 p = n->p.parent;
437 s = sibling(n);
438 while(isblack(p) && isblack(s) && isint(s) &&
439 isblack(s->c.child.left) && isblack(s->c.child.right)) {
440 setred(s);
441 n = p;
442 if (isroot(n)) return;
443 p = n->p.parent;
444 s = sibling(n);
447 if (isblack(p) && isred(s)) { /* Rotation 2.3b */
448 single_rotate(p, isright(n));
449 setred(p);
450 setblack(s);
451 s = sibling(n);
454 { Rb_node x, z; char il;
456 if (isext(s)) {
457 fprintf(stderr, "DELETION ERROR: sibling not internal\n");
458 exit(1);
461 il = isleft(n);
462 x = il ? s->c.child.left : s->c.child.right ;
463 z = sibling(x);
465 if (isred(z)) { /* Rotation 2.3f */
466 single_rotate(p, !il);
467 setblack(z);
468 if (isred(p)) setred(s); else setblack(s);
469 setblack(p);
470 } else if (isblack(x)) { /* Recoloring only (2.3c) */
471 if (isred(s) || isblack(p)) {
472 fprintf(stderr, "DELETION ERROR: 2.3c not quite right\n");
473 exit(1);
475 setblack(p);
476 setred(s);
477 return;
478 } else if (isred(p)) { /* 2.3d */
479 single_rotate(s, il);
480 single_rotate(p, !il);
481 setblack(x);
482 setred(s);
483 return;
484 } else { /* 2.3e */
485 single_rotate(s, il);
486 single_rotate(p, !il);
487 setblack(x);
488 return;
494 void rb_print_tree(Rb_node t, int level)
496 int i;
497 if (ishead(t) && t->p.parent == t) {
498 printf("tree %p is empty\n", DONT_COMPLAIN t);
499 } else if (ishead(t)) {
500 printf("Head: %p. Root = %p\n", DONT_COMPLAIN t, DONT_COMPLAIN t->p.root);
501 rb_print_tree(t->p.root, 0);
502 } else {
503 if (isext(t)) {
504 for (i = 0; i < level; i++) putchar(' ');
505 printf("Ext node %p: %c,%c: p=%p, k=%s\n",
506 DONT_COMPLAIN t, isred(t)?'R':'B', isleft(t)?'l':'r',
507 DONT_COMPLAIN t->p.parent, DONT_COMPLAIN t->k.key);
508 } else {
509 rb_print_tree(t->c.child.left, level+2);
510 rb_print_tree(t->c.child.right, level+2);
511 for (i = 0; i < level; i++) putchar(' ');
512 printf("Int node %p: %c,%c: l=%p, r=%p, p=%p, lr=(%s,%s)\n",
513 DONT_COMPLAIN t, isred(t)?'R':'B', isleft(t)?'l':'r',
514 DONT_COMPLAIN t->c.child.left, DONT_COMPLAIN t->c.child.right,
515 DONT_COMPLAIN t->p.parent, DONT_COMPLAIN t->k.lext->k.key,
516 DONT_COMPLAIN t->v.rext->k.key);
521 void rb_iprint_tree(Rb_node t, int level)
523 int i;
524 if (ishead(t) && t->p.parent == t) {
525 printf("tree %p is empty\n", DONT_COMPLAIN t);
526 } else if (ishead(t)) {
527 printf("Head: %p. Root = %p, < = %p, > = %p\n",
528 DONT_COMPLAIN t, DONT_COMPLAIN t->p.root,
529 DONT_COMPLAIN t->c.list.blink,
530 DONT_COMPLAIN t->c.list.flink);
531 rb_iprint_tree(t->p.root, 0);
532 } else {
533 if (isext(t)) {
534 for (i = 0; i < level; i++) putchar(' ');
535 printf("Ext node %p: %c,%c: p=%p, <=%p, >=%p k=%d\n",
536 DONT_COMPLAIN t, isred(t)?'R':'B', isleft(t)?'l':'r',
537 DONT_COMPLAIN t->p.parent, DONT_COMPLAIN t->c.list.blink,
538 DONT_COMPLAIN t->c.list.flink, t->k.ikey);
539 } else {
540 rb_iprint_tree(t->c.child.left, level+2);
541 rb_iprint_tree(t->c.child.right, level+2);
542 for (i = 0; i < level; i++) putchar(' ');
543 printf("Int node %p: %c,%c: l=%p, r=%p, p=%p, lr=(%d,%d)\n",
544 DONT_COMPLAIN t, isred(t)?'R':'B', isleft(t)?'l':'r',
545 DONT_COMPLAIN t->c.child.left, DONT_COMPLAIN t->c.child.right,
546 DONT_COMPLAIN t->p.parent, t->k.lext->k.ikey, t->v.rext->k.ikey);
551 int rb_nblack(Rb_node n)
553 int nb;
554 if (ishead(n) || isint(n)) {
555 fprintf(stderr, "ERROR: rb_nblack called on a non-external node %p\n",
556 DONT_COMPLAIN n);
557 exit(1);
559 nb = 0;
560 while(!ishead(n)) {
561 if (isblack(n)) nb++;
562 n = n->p.parent;
564 return nb;
567 int rb_plength(Rb_node n)
569 int pl;
570 if (ishead(n) || isint(n)) {
571 fprintf(stderr, "ERROR: rb_plength called on a non-external node %p\n",
572 DONT_COMPLAIN n);
573 exit(1);
575 pl = 0;
576 while(!ishead(n)) {
577 pl++;
578 n = n->p.parent;
580 return pl;
583 void rb_free_tree(Rb_node n)
585 if (!ishead(n)) {
586 fprintf(stderr, "ERROR: Rb_free_tree called on a non-head node\n");
587 exit(1);
590 while(rb_first(n) != rb_nil(n)) {
591 rb_delete_node(rb_first(n));
593 free(n);
596 void *rb_val(Rb_node n)
598 return n->v.val;
601 Rb_node rb_insert_a(Rb_node nd, const void *key, void *val)
603 return rb_insert_b(nd->c.list.flink, key, val);
606 Rb_node rb_insert(Rb_node tree, const char *key, void *val)
608 return rb_insert_b(rb_find_key(tree, key), key, val);
611 Rb_node rb_inserti(Rb_node tree, int ikey, void *val)
613 return rb_insert_b(rb_find_ikey(tree, ikey), (void *) ikey, val);
616 Rb_node rb_insertg(Rb_node tree, const void *key, void *val, Rb_compfn *func)
618 return rb_insert_b(rb_find_gkey(tree, key, func), key, val);
621 Rb_node rb_insertp(Rb_node tree, const void *key, void *val)
623 return rb_insertg(tree, key, val, ptrcmp);