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; }
node_t *ct_prev_node(node_t *root, node_t *node) { node_t *prev; node_t *tmp; if ((prev = LEFT_NODE(node)) != NULL) { // find the largest node of left-subtee while ( (tmp=RIGHT_NODE(prev)) != NULL) { prev = tmp; } return prev; } else { // node has no left sub-tree node_t *parent = PARENT_NODE(node); while (1) { if (parent == NULL) { return NULL; } else if (LEFT_NODE(parent) == node) { node = parent; parent = PARENT_NODE(node); } else { return parent; } } } }
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; }
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 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 node_t * ct_min_node(node_t *root) { if (root == NULL) return NULL; while (LEFT_NODE(root) != NULL) root = LEFT_NODE(root); return root; }
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; } } }
extern void ct_delete_tree(node_t *root) { if (root == NULL) return; if (LEFT_NODE(root) != NULL) { ct_delete_tree(LEFT_NODE(root)); } if (RIGHT_NODE(root) != NULL) { ct_delete_tree(RIGHT_NODE(root)); } ct_delete_node(root); }
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; } }
node_t *ct_succ_node(node_t *root, node_t *node) { node_t *succ; node_t *tmp; if ( (succ = RIGHT_NODE(node)) != NULL) { /* find smallest node of right subtree */ while ( (tmp=LEFT_NODE(succ)) != NULL) { succ = tmp; } return succ; } else { // node has no right tree node_t *parent = PARENT_NODE(node); while (1) { if (parent == NULL) { return NULL; } else if (RIGHT_NODE(parent) == node) { node = parent; parent = PARENT_NODE(node); } else { // assert(LEFT_NODE(parent) == node); return parent; } } } }
void ct_bintree_keys(node_t *root, PyObject *list) { if (root == NULL) { return ; } ct_bintree_keys(LEFT_NODE(root), list); PyList_Append(list, KEY(root)); ct_bintree_keys(RIGHT_NODE(root), list); }
void ct_delete_tree(node_t *root) { if (root == NULL) return ; ct_delete_tree(LEFT_NODE(root)); ct_delete_tree(RIGHT_NODE(root)); ct_delete_node(root); }
node_t *ct_min_node(node_t *root) { node_t *left; if (root == NULL) return NULL; while ((left = LEFT_NODE(root)) != NULL) { root = left; } return root; }
static void ct_delete_node(node_t *node) { if (node != NULL) { Py_XDECREF(KEY(node)); Py_XDECREF(VALUE(node)); LEFT_NODE(node) = NULL; RIGHT_NODE(node) = NULL; PyMem_Free(node); } }
int ct_validate(node_t *root) { PyObject *key; if (root == NULL) return 1; if (PARENT_NODE(root) != NULL) { PyErr_SetString(PyExc_AssertionError, "parent of root is not null"); return 0; } 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); return ct_validate_range(LEFT_NODE(root), NULL, key) && ct_validate_range(RIGHT_NODE(root), key, NULL); }
extern node_t * ct_node_at(node_t *root, int index) { node_t *node = root; int counter = 0; int go_down = 1; node_stack_t *stack; if (index < 0) return NULL; stack = stack_init(32); for(;;) { if ((LEFT_NODE(node) != NULL) && go_down) { stack_push(stack, node); node = LEFT_NODE(node); } else { if (counter == index) { stack_delete(stack); return node; } counter++; if (RIGHT_NODE(node) != NULL) { node = RIGHT_NODE(node); go_down = 1; } else { if (stack_is_empty(stack)) { stack_delete(stack); return NULL; } node = stack_pop(stack); go_down = 0; } } } }
static node_t * ct_new_node(PyObject *key, PyObject *value, int xdata) { node_t *new_node = PyMem_Malloc(sizeof(node_t)); if (new_node != NULL) { KEY(new_node) = key; Py_INCREF(key); VALUE(new_node) = value; Py_INCREF(value); LEFT_NODE(new_node) = NULL; RIGHT_NODE(new_node) = NULL; XDATA(new_node) = xdata; } return new_node; }
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_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_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; }