static int ct_validate_range(node_t *root, PyObject *minkey, PyObject *maxkey) { PyObject *key; if (root == NULL) return 1; if (!(LEFT_NODE(root) == NULL || PARENT_NODE(LEFT_NODE(root)) == root )) { PyErr_SetString(PyExc_AssertionError, "left node parent is wrong"); return 0; } if (!(RIGHT_NODE(root) == NULL || PARENT_NODE(RIGHT_NODE(root)) == root )) { PyErr_SetString(PyExc_AssertionError, "right node parent is wrong"); return 0; } key = KEY(root); if (minkey != NULL) { if (ct_compare(key, minkey) <= 0) { PyErr_SetString(PyExc_AssertionError, "key order is wrong"); return 0; } } if (maxkey != NULL) { if (ct_compare(key, maxkey) >= 0) { PyErr_SetString(PyExc_AssertionError, "key order is wrong"); return 0; } } return 1; }
extern node_t * ct_prev_node(node_t *root, PyObject *key) { node_t *prev = NULL; node_t *node = root; int cval; while (node != NULL) { cval = ct_compare(key, KEY(node)); if (cval == 0) break; else if (cval < 0) node = LEFT_NODE(node); else { if ((prev == NULL) || (ct_compare(KEY(node), KEY(prev)) > 0)) prev = node; node = RIGHT_NODE(node); } } if (node == NULL) return NULL; if (LEFT_NODE(node) != NULL) { node = LEFT_NODE(node); while (RIGHT_NODE(node) != NULL) node = RIGHT_NODE(node); if (prev == NULL) prev = node; else if (ct_compare(KEY(node), KEY(prev)) > 0) prev = node; } return prev; }
extern node_t * ct_succ_node(node_t *root, PyObject *key) { node_t *succ = NULL; node_t *node = root; int cval; while (node != NULL) { cval = ct_compare(key, KEY(node)); if (cval == 0) break; else if (cval < 0) { if ((succ == NULL) || (ct_compare(KEY(node), KEY(succ)) < 0)) succ = node; node = LEFT_NODE(node); } else node = RIGHT_NODE(node); } if (node == NULL) return NULL; if (RIGHT_NODE(node) != NULL) { node = RIGHT_NODE(node); while (LEFT_NODE(node) != NULL) node = LEFT_NODE(node); if (succ == NULL) succ = node; else if (ct_compare(KEY(node), KEY(succ)) < 0) succ = node; } return succ; }
int ct_bintree_insert(node_t **rootaddr, PyObject *key, PyObject *value) { int cval; node_t *parent = NULL; while (1) { node_t *root = *rootaddr; if (root == NULL) { node_t *node = ct_new_node(parent, key, value, 0); if (node == NULL) return -1; *rootaddr = node; return 1; } cval = ct_compare(key, KEY(root)); if (cval < 0) { // use left tree rootaddr = &LEFT_NODE(root); } else if (cval > 0) { rootaddr = &RIGHT_NODE(root); } else { /* key exists, replace value object? no! */ // Py_XDECREF(VALUE(root)); /* release old value object */ // VALUE(root) = value; /* set new value object */ // Py_INCREF(value); /* take new value object */ return 0; } parent = root; } }
extern int ct_index_of(node_t *root, PyObject *key) { node_t *node = root; int index = 0; int go_down = 1; node_stack_t *stack; stack = stack_init(32); for (;;) { if ((LEFT_NODE(node) != NULL) && go_down) { stack_push(stack, node); node = LEFT_NODE(node); } else { if (ct_compare(KEY(node), key) == 0) { stack_delete(stack); return index; } index++; if (RIGHT_NODE(node) != NULL) { node = RIGHT_NODE(node); go_down = 1; } else { if (stack_is_empty(stack)) { stack_delete(stack); return -1; } node = stack_pop(stack); go_down = 0; } } } }
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; } } }
node_t * ct_find_node(node_t *root, PyObject *key) { int res; while (root != NULL) { res = ct_compare(key, KEY(root)); if (res == 0) { return root; } else { root = LINK(root, (res > 0)); } } return NULL; }
extern int ct_bintree_insert(node_t **rootaddr, PyObject *key, PyObject *value) { node_t *parent, *node; int direction, cval; node = *rootaddr; if (node == NULL) { node = ct_new_node(key, value, 0); if (node == NULL) return -1; *rootaddr = node; } else { direction = LEFT; parent = NULL; while (1) { if (node == NULL) { node = ct_new_node(key, value, 0); if (node == NULL) return -1; LINK(parent, direction) = node; return 1; } cval = ct_compare(key, KEY(node)); if (cval == 0) { Py_XDECREF(VALUE(node)); VALUE(node) = value; Py_INCREF(value); return 0; } else { parent = node; direction = (cval < 0) ? LEFT : RIGHT; node = LINK(node, direction); } } } return 1; }
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 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 avl_insert(node_t **rootaddr, PyObject *key, PyObject *value) { node_t *root = *rootaddr; if (root == NULL) { root = avl_new_node(key, value); if (root == NULL) return -1; } else { node_t *it, *up[32]; int upd[32], top = 0; int done = 0; int cmp_res; it = root; for (;;) { cmp_res = ct_compare(KEY(it), key); if (cmp_res == 0) { Py_XDECREF(VALUE(it)); VALUE(it) = value; Py_INCREF(value); return 0; } upd[top] = (cmp_res < 0); up[top++] = it; if (it->link[upd[top - 1]] == NULL) break; it = it->link[upd[top - 1]]; } it->link[upd[top - 1]] = avl_new_node(key, value); if (it->link[upd[top - 1]] == NULL) return -1; while (--top >= 0 && !done) { int lh, rh, max; cmp_res = ct_compare(KEY(up[top]), key); lh = height(up[top]->link[upd[top]]); rh = height(up[top]->link[!upd[top]]); if (lh - rh == 0) done = 1; 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]; done = 1; } lh = height(up[top]->link[upd[top]]); rh = height(up[top]->link[!upd[top]]); max = avl_max(lh, rh); BALANCE(up[top]) = max + 1; } } (*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); }
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; }