extern int ct_bintree_remove(node_t **rootaddr, PyObject *key) { node_t *node, *parent, *replacement; int direction, cmp_res, down_dir; node = *rootaddr; if (node == NULL) return 0; parent = NULL; direction = 0; while (1) { cmp_res = ct_compare(key, KEY(node)); if (cmp_res == 0) { if ((LEFT_NODE(node) != NULL) && (RIGHT_NODE(node) != NULL)) { parent = node; direction = RIGHT; replacement = RIGHT_NODE(node); while (LEFT_NODE(replacement) != NULL) { parent = replacement; direction = LEFT; replacement = LEFT_NODE(replacement); } LINK(parent, direction) = RIGHT_NODE(replacement); ct_swap_data(node, replacement); node = replacement; } else { down_dir = (LEFT_NODE(node) == NULL) ? RIGHT : LEFT; if (parent == NULL) { *rootaddr = LINK(node, down_dir); } else { LINK(parent, direction) = LINK(node, down_dir); } } ct_delete_node(node); return 1; } else { direction = (cmp_res < 0) ? LEFT : RIGHT; parent = node; node = LINK(node, direction); if (node == NULL) return 0; } } }
void ct_bintree_remove(node_t **rootaddr, node_t *node) { node_t **pnode = NULL; node_t *tmp; if (*rootaddr == node) { // the node is the root pnode = rootaddr; } else { node_t *parent = PARENT_NODE(node); if (LEFT_NODE(parent) == node) { pnode = &LEFT_NODE(parent); } else { pnode = &RIGHT_NODE(parent); } } if (LEFT_NODE(node) == NULL) { // replace the root with the right sub-tree tmp = *pnode = RIGHT_NODE(node); if (tmp != NULL) { PARENT_NODE(tmp) = PARENT_NODE(node); } ct_delete_node(node); } else if (RIGHT_NODE(node) == NULL) { // replace the node with the left sub-tree tmp = *pnode = LEFT_NODE(node); PARENT_NODE(tmp) = PARENT_NODE(node); ct_delete_node(node); } else { // both left and right sub-tree is non-null, replace by smallest key in right sub-tree node_t **pleftmost = &RIGHT_NODE(node); node_t *leftmost = RIGHT_NODE(node); // assert leftmost != NULL while ((tmp = LEFT_NODE(leftmost)) != NULL) { pleftmost = &LEFT_NODE(leftmost); leftmost = tmp; } // found the leftmost node, copy its data to the root, then remove the left most node ct_swap_data(node, leftmost); tmp = *pleftmost = RIGHT_NODE(leftmost); if (tmp != NULL) { PARENT_NODE(tmp) = PARENT_NODE(leftmost); } ct_delete_node(leftmost); } }
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 avl_remove(node_t **rootaddr, PyObject *key) { node_t *root = *rootaddr; int cmp_res; if (root != NULL) { node_t *it, *up[32]; int upd[32], top = 0; it = root; for (;;) { if (it == NULL) return 0; cmp_res = ct_compare(KEY(it), key); if (cmp_res == 0) break; upd[top] = (cmp_res < 0); up[top++] = it; it = it->link[upd[top - 1]]; } if (it->link[0] == NULL || it->link[1] == NULL) { int dir = it->link[0] == NULL; if (top != 0) up[top - 1]->link[upd[top - 1]] = it->link[dir]; else root = it->link[dir]; ct_delete_node(it); } else { node_t *heir = it->link[1]; upd[top] = 1; up[top++] = it; while ( heir->link[0] != NULL ) { upd[top] = 0; up[top++] = heir; heir = heir->link[0]; } ct_swap_data(it, heir); up[top - 1]->link[up[top - 1] == it] = heir->link[1]; ct_delete_node(heir); } while (--top >= 0) { int lh = height(up[top]->link[upd[top]]); int rh = height(up[top]->link[!upd[top]]); int max = avl_max(lh, rh); BALANCE(up[top]) = max + 1; if (lh - rh == -1) break; if (lh - rh <= -2) { node_t *a = up[top]->link[!upd[top]]->link[upd[top]]; node_t *b = up[top]->link[!upd[top]]->link[!upd[top]]; if (height(a) <= height(b)) up[top] = avl_single(up[top], upd[top]); else up[top] = avl_double(up[top], upd[top]); if (top != 0) up[top - 1]->link[upd[top - 1]] = up[top]; else root = up[0]; } } } (*rootaddr) = root; return 1; }
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); }