void jrb_iprint_tree(JRB t, int level) { int i; if (ishead(t) && t->parent == t) { printf("tree 0x%x is empty\n", t); } else if (ishead(t)) { printf("Head: 0x%x. Root = 0x%x, < = 0x%x, > = 0x%x\n", t, t->parent, t->blink, t->flink); jrb_iprint_tree(t->parent, 0); } else { if (isext(t)) { for (i = 0; i < level; i++) putchar(' '); printf("Ext node 0x%x: %c,%c: p=0x%x, <=0x%x, >=0x%x k=%d\n", t, isred(t)?'R':'B', isleft(t)?'l':'r', t->parent, t->blink, t->flink, t->key.i); } else { jrb_iprint_tree(t->flink, level+2); jrb_iprint_tree(t->blink, level+2); for (i = 0; i < level; i++) putchar(' '); printf("Int node 0x%x: %c,%c: l=0x%x, r=0x%x, p=0x%x, lr=(%d,%d)\n", t, isred(t)?'R':'B', isleft(t)?'l':'r', t->flink, t->blink, t->parent, getlext(t)->key.i, getrext(t)->key.i); } } }
void rb_iprint_tree(Rb_node t, int level) { int i; if (ishead(t) && t->p.parent == t) { printf("tree 0x%p is empty\n", (void *) t); } else if (ishead(t)) { printf("Head: 0x%p. Root = 0x%p, < = 0x%p, > = 0x%p\n", (void *) t, (void *) t->p.root, (void *) t->c.list.blink, (void *) t->c.list.flink); rb_iprint_tree(t->p.root, 0); } else { if (isext(t)) { for (i = 0; i < level; i++) putchar(' '); printf("Ext node 0x%p: %c,%c: p=0x%p, <=0x%p, >=0x%p k=%d\n", (void *) t, isred(t)?'R':'B', isleft(t)?'l':'r', (void *) t->p.parent, (void *) t->c.list.blink, (void *) t->c.list.flink, t->k.ikey); } else { rb_iprint_tree(t->c.child.left, level+2); rb_iprint_tree(t->c.child.right, level+2); for (i = 0; i < level; i++) putchar(' '); printf("Int node 0x%p: %c,%c: l=0x%p, r=0x%p, p=0x%p, lr=(%d,%d)\n", (void *) t, isred(t)?'R':'B', isleft(t)?'l':'r', (void *) t->c.child.left, (void *) t->c.child.right, (void *) t->p.parent, t->k.lext->k.ikey, t->v.rext->k.ikey); } } }
static rbtree_node* fixup(rbtree_node *h) { if ( isred(h->right) ) h = rotate_left(h); if ( isred(h->left) && isred(h->left->left) ) h = rotate_right(h); if ( isred(h->left) && isred(h->right) ) colorflip(h); return set_num_nodes(h); }
static rbtree_node* delete_min(rbtree_node *h, VALUE *deleted_value) { if ( !h->left ) { if(deleted_value) *deleted_value = h->value; free(h); return NULL; } if ( !isred(h->left) && !isred(h->left->left) ) h = move_red_left(h); h->left = delete_min(h->left, deleted_value); return fixup(h); }
static rbtree_node* delete_max(rbtree_node *h, VALUE *deleted_value) { if ( isred(h->left) ) h = rotate_right(h); if ( !h->right ) { *deleted_value = h->value; free(h); return NULL; } if ( !isred(h->right) && !isred(h->right->left) ) h = move_red_right(h); h->right = delete_max(h->right, deleted_value); return fixup(h); }
static rbtree_node* move_red_right(rbtree_node *h) { colorflip(h); if ( isred(h->left->left) ) { h = rotate_right(h); colorflip(h); } return h; }
static rbtree_node* insert(rbtree *tree, rbtree_node *node, VALUE key, VALUE value) { int cmp; // This slot is empty, so we insert our new node if(!node) { rbtree_node *new_node = ALLOC(rbtree_node); new_node->key = key; new_node->value = value; new_node->color = RED; new_node->height = 1; new_node->num_nodes = 1; new_node->left = NULL; new_node->right = NULL; return new_node; } // Insert left or right, recursively cmp = tree->compare_function(key, node->key); if (cmp == 0) { node->value = value; } else if (cmp == -1) { node->left = insert(tree, node->left, key, value); } else { node->right = insert(tree, node->right, key, value); } // Fix our tree to keep left-lean if (isred(node->right)) { node = rotate_left(node); } if (isred(node->left) && isred(node->left->left)) { node = rotate_right(node); } if ( isred(node->left) && isred(node->right) ) { colorflip(node); } return set_num_nodes(node); }
static void recolor(JRB n) { JRB p, gp, s; int done = 0; while (!done) { if (isroot(n)) { setblack(n); return; } p = n->parent; if (isblack(p)) return; if (isroot(p)) { setblack(p); return; } gp = p->parent; s = sibling(p); if (isred(s)) { setblack(p); setred(gp); setblack(s); n = gp; } else { done = 1; } } /* p's sibling is black, p is red, gp is black */ if ((isleft(n) == 0) == (isleft(p) == 0)) { single_rotate(gp, isleft(n)); setblack(p); setred(gp); } else { single_rotate(p, isleft(n)); single_rotate(gp, isleft(n)); setblack(n); setred(gp); } }
void jrb_delete_node(JRB n) { JRB s, p, gp; char ir; if (isint(n)) { fprintf(stderr, "Cannot delete an internal node: 0x%p\n", (void *)n); exit(1); } if (ishead(n)) { fprintf(stderr, "Cannot delete the head of an jrb_tree: 0x%p\n", (void *)n); exit(1); } delete_item(n); /* Delete it from the list */ p = n->parent; /* The only node */ if (isroot(n)) { p->parent = p; free(n); return; } s = sibling(n); /* The only node after deletion */ if (isroot(p)) { s->parent = p->parent; s->parent->parent = s; setroot(s); free(p); free(n); return; } gp = p->parent; /* Set parent to sibling */ s->parent = gp; if (isleft(p)) { gp->flink = s; setleft(s); } else { gp->blink = s; setright(s); } ir = isred(p); free(p); free(n); if (isext(s)) { /* Update proper rext and lext values */ p = lprev(s); if (!ishead(p)) setrext(p, s); p = rprev(s); if (!ishead(p)) setlext(p, s); } else if (isblack(s)) { fprintf(stderr, "DELETION PROB -- sib is black, internal\n"); exit(1); } else { p = lprev(s); if (!ishead(p)) setrext(p, s->flink); p = rprev(s); if (!ishead(p)) setlext(p, s->blink); setblack(s); return; } if (ir) return; /* Recolor */ n = s; p = n->parent; s = sibling(n); while(isblack(p) && isblack(s) && isint(s) && isblack(s->flink) && isblack(s->blink)) { setred(s); n = p; if (isroot(n)) return; p = n->parent; s = sibling(n); } if (isblack(p) && isred(s)) { /* Rotation 2.3b */ single_rotate(p, isright(n)); setred(p); setblack(s); s = sibling(n); } { JRB x, z; char il; if (isext(s)) { fprintf(stderr, "DELETION ERROR: sibling not internal\n"); exit(1); } il = isleft(n); x = il ? s->flink : s->blink ; z = sibling(x); if (isred(z)) { /* Rotation 2.3f */ single_rotate(p, !il); setblack(z); if (isred(p)) setred(s); else setblack(s); setblack(p); } else if (isblack(x)) { /* Recoloring only (2.3c) */ if (isred(s) || isblack(p)) { fprintf(stderr, "DELETION ERROR: 2.3c not quite right\n"); exit(1); } setblack(p); setred(s); return; } else if (isred(p)) { /* 2.3d */ single_rotate(s, il); single_rotate(p, !il); setblack(x); setred(s); return; } else { /* 2.3e */ single_rotate(s, il); single_rotate(p, !il); setblack(x); return; } } }