int rb_remove ( const RB_TYPE *rbt, RB_TREE *root, void *data ) { RB_NODE *node = *root; if ( node != NULL ) { RB_NODE head = {{0,0},0}; /* False tree root */ RB_NODE *q, *p, *g; /* Helpers */ RB_NODE *f = NULL; /* Found item */ int dir = 1, cmp; /* Set up helpers */ q = &head; g = p = NULL; q->link[1] = node; /* Search and push a red down */ while ( q->link[dir] != NULL ) { int last = dir; /* Update helpers */ g = p, p = q; q = q->link[dir]; cmp = (*rbt->cmp)(rbt->ctx,q+1,data); dir = cmp < 0; /* Save found node */ if ( cmp == 0 ) f = q; /* Push the red node down */ if ( !is_red ( q ) && !is_red ( q->link[dir] ) ) { if ( is_red ( q->link[!dir] ) ) p = p->link[last] = rb_single ( q, dir ); else if ( !is_red ( q->link[!dir] ) ) { RB_NODE *s = p->link[!last]; if ( s != NULL ) { if ( !is_red ( s->link[!last] ) && !is_red ( s->link[last] ) ) { /* Color flip */ p->red = 0; s->red = 1; q->red = 1; } else { int dir2 = g->link[1] == p; if ( is_red ( s->link[last] ) ) g->link[dir2] = rb_double ( p, last ); else if ( is_red ( s->link[!last] ) ) g->link[dir2] = rb_single ( p, last ); /* Ensure correct coloring */ q->red = g->link[dir2]->red = 1; g->link[dir2]->link[0]->red = 0; g->link[dir2]->link[1]->red = 0; } } } } } /* Replace and remove if found */ if ( f != NULL ) { if (f!=q) memcpy(f+1,q+1,rbt->iSize-sizeof(RB_NODE)); p->link[p->link[1] == q] = q->link[q->link[0] == NULL]; if ( !rbt->delnode ) free(q); else (*rbt->delnode)(rbt->ctx,q); } /* Update root and make it black */ *root = node = head.link[1]; if ( node != NULL ) node->red = 0; } return 1; }
int rb_insert( const RB_TYPE *rbt, RB_TREE *root, void *data ) { RB_NODE *node = *root; int cmp; int ins = 0; if ( node == NULL ) { /* Empty tree case */ *root = node = make_node(rbt,data); assert(node!=NULL); ins = 1; } else { RB_NODE head = {{0,0},0}; /* False tree root */ RB_NODE *g, *t; /* Grandparent & parent */ RB_NODE *p, *q; /* Iterator & parent */ int dir = 0, last=0; /* Set up helpers */ t = &head; g = p = NULL; q = t->link[1] = node; /* Search down the tree */ for ( ; ; ) { if ( q == NULL ) { /* Insert new node at the bottom */ p->link[dir] = q = make_node(rbt,data); assert(q!=NULL); ins = 1; } else if ( is_red ( q->link[0] ) && is_red ( q->link[1] ) ) { /* Color flip */ q->red = 1; q->link[0]->red = 0; q->link[1]->red = 0; } /* Fix red violation */ if ( is_red ( q ) && is_red ( p ) ) { int dir2 = t->link[1] == g; if ( q == p->link[last] ) t->link[dir2] = rb_single ( g, !last ); else t->link[dir2] = rb_double ( g, !last ); } /* Stop if found */ cmp = (*rbt->cmp)(rbt->ctx,q+1,data); if ( cmp == 0 ) break; last = dir; dir = cmp < 0; /* Update helpers */ if ( g != NULL ) t = g; g = p, p = q; q = q->link[dir]; } /* Update root */ *root = node = head.link[1]; } /* Make root black */ node->red = 0; return ins; }
extern int rb_remove(node_t **rootaddr, node_t *_node) { PyObject *key = KEY(_node); node_t *root = *rootaddr; node_t head = { { NULL } }; /* False tree root */ node_t *q, *p, *g; /* Helpers */ node_t *f = NULL; /* Found item */ node_t *tmp; int dir = 1; if (root == NULL) return 0; /* Set up our helpers */ q = &head; g = p = NULL; RIGHT_NODE(q) = root; /* Search and push a red node down to fix red violations as we go */ while (q->link[dir] != NULL) { int last = dir; int cmp_res; /* Move the helpers down */ g = p, p = q; q = q->link[dir]; cmp_res = ct_compare(KEY(q), key); dir = cmp_res < 0; /* Save the node with matching data and keep going; we'll do removal tasks at the end */ if (cmp_res == 0) f = q; /* Push the red node down with rotations and color flips */ if (!is_red(q) && !is_red(q->link[dir])) { if (is_red(q->link[!dir])) { tmp = rb_single(q, dir); PARENT_NODE(tmp) = p; p = p->link[last] = tmp; } else if (!is_red(q->link[!dir])) { node_t *s = p->link[!last]; if (s != NULL) { if (!is_red(s->link[!last]) && !is_red(s->link[last])) { /* Color flip */ RED(p) = 0; RED(s) = 1; RED(q) = 1; } else { int dir2 = g->link[1] == p; if (is_red(s->link[last])) { tmp = g->link[dir2] = rb_double(p, last); PARENT_NODE(tmp) = g; } else if (is_red(s->link[!last])) { tmp = g->link[dir2] = rb_single(p, last); PARENT_NODE(tmp) = g; } /* Ensure correct coloring */ RED(q) = RED(g->link[dir2]) = 1; RED(g->link[dir2]->link[0]) = 0; RED(g->link[dir2]->link[1]) = 0; } } } } } /* Replace and remove the saved node */ if (f != NULL) { ct_swap_data(f, q); p->link[p->link[1] == q] = q->link[q->link[0] == NULL]; ct_delete_node(q); } /* Update the root (it may be different) */ root = head.link[1]; /* Make the root black for simplified logic */ if (root != NULL) { RED(root) = 0; PARENT_NODE(root) = NULL; } *rootaddr = root; return (f != NULL); }
extern int rb_insert(node_t **rootaddr, PyObject *key, PyObject *value) { int new_node = 0; node_t *root = *rootaddr; if (root == NULL) { // case 1, root == NULL root = rb_new_node(NULL, key, value); new_node = 1; if (root == NULL) return -1; // got no memory } else { node_t head; /* False tree root */ node_t *g, *t; /* Grandparent & parent */ node_t *p, *q; /* Iterator & parent */ int dir = 0; int last = 0; /* Set up our helpers */ t = &head; g = NULL; p = NULL; RIGHT_NODE(t) = root; LEFT_NODE(t) = NULL; q = RIGHT_NODE(t); /* Search down the tree for a place to insert */ for (;;) { int cmp_res; if (q == NULL) { /* Insert a new node at the first null link */ q = rb_new_node(p, key, value); new_node = 1; p->link[dir] = q; if (q == NULL) return -1; // get no memory } else if (is_red(q->link[0]) && is_red(q->link[1])) { /* Simple red violation: color flip */ RED(q) = 1; RED(q->link[0]) = 0; RED(q->link[1]) = 0; } if (is_red(q) && is_red(p)) { /* Hard red violation: rotations necessary */ int dir2 = (t->link[1] == g); if (q == p->link[last]) { node_t * tmp = t->link[dir2] = rb_single(g, !last); PARENT_NODE(tmp) = t; } else { node_t *tmp = t->link[dir2] = rb_double(g, !last); PARENT_NODE(tmp) = t; } } /* Stop working if we inserted a new node. */ if (new_node) break; cmp_res = ct_compare(KEY(q), key); if (cmp_res == 0) { /* if key exists */ // Py_XDECREF(VALUE(q)); /* release old value object */ // VALUE(q) = value; set new value object // Py_INCREF(value); /* take new value object */ break; } last = dir; dir = (cmp_res < 0); /* Move the helpers down */ if (g != NULL) t = g; g = p; p = q; q = q->link[dir]; } /* Update the root (it may be different) */ root = head.link[1]; } /* Make the root black for simplified logic */ RED(root) = 0; (*rootaddr) = root; PARENT_NODE(root) = NULL; return new_node; }
extern int rb_remove(node_t **rootaddr, PyObject *key) { node_t *root = *rootaddr; node_t head = { { NULL } }; node_t *q, *p, *g; node_t *f = NULL; int dir = 1; if (root == NULL) return 0; q = &head; g = p = NULL; RIGHT_NODE(q) = root; while (q->link[dir] != NULL) { int last = dir; int cmp_res; g = p, p = q; q = q->link[dir]; cmp_res = ct_compare(KEY(q), key); dir = cmp_res < 0; if (cmp_res == 0) f = q; if (!is_red(q) && !is_red(q->link[dir])) { if (is_red(q->link[!dir])) p = p->link[last] = rb_single(q, dir); else if (!is_red(q->link[!dir])) { node_t *s = p->link[!last]; if (s != NULL) { if (!is_red(s->link[!last]) && !is_red(s->link[last])) { RED(p) = 0; RED(s) = 1; RED(q) = 1; } else { int dir2 = g->link[1] == p; if (is_red(s->link[last])) g->link[dir2] = rb_double(p, last); else if (is_red(s->link[!last])) g->link[dir2] = rb_single(p, last); RED(q) = RED(g->link[dir2]) = 1; RED(g->link[dir2]->link[0]) = 0; RED(g->link[dir2]->link[1]) = 0; } } } } } if (f != NULL) { ct_swap_data(f, q); p->link[p->link[1] == q] = q->link[q->link[0] == NULL]; ct_delete_node(q); } root = head.link[1]; if (root != NULL) RED(root) = 0; *rootaddr = root; return (f != NULL); }
extern int rb_insert(node_t **rootaddr, PyObject *key, PyObject *value) { node_t *root = *rootaddr; if (root == NULL) { root = rb_new_node(key, value); if (root == NULL) return -1; } else { node_t head; node_t *g, *t; node_t *p, *q; int dir = 0; int last = 0; int new_node = 0; t = &head; g = NULL; p = NULL; RIGHT_NODE(t) = root; LEFT_NODE(t) = NULL; q = RIGHT_NODE(t); for (;;) { int cmp_res; if (q == NULL) { q = rb_new_node(key, value); p->link[dir] = q; new_node = 1; if (q == NULL) return -1; } else if (is_red(q->link[0]) && is_red(q->link[1])) { RED(q) = 1; RED(q->link[0]) = 0; RED(q->link[1]) = 0; } if (is_red(q) && is_red(p)) { int dir2 = (t->link[1] == g); if (q == p->link[last]) t->link[dir2] = rb_single(g, !last); else t->link[dir2] = rb_double(g, !last); } if (new_node) break; cmp_res = ct_compare(KEY(q), key); if (cmp_res == 0) { Py_XDECREF(VALUE(q)); VALUE(q) = value; Py_INCREF(value); return 0; } last = dir; dir = (cmp_res < 0); if (g != NULL) t = g; g = p; p = q; q = q->link[dir]; } root = head.link[1]; } RED(root) = 0; (*rootaddr) = root; return 1; }