/* rbt_t */
static void rbt_free(void* v_tree){
- rbt_t* tree = (rbt_t*) v_tree;
- assert(NULL != tree);
- if(tree->root) mem_release(tree->root);
+ rbt_t* tree = (rbt_t*) v_tree;
- if(tree && tree->root) mem_release(tree->root);
++ assert(NULL != tree);
++ if(tree->root) mem_release(tree->root);
}
rbt_t* rbt_new(comparator_t comparator){
/* rbt_node_t */
static void rbt_node_free(void* v_node){
- rbt_node_t* node = (rbt_node_t*) v_node;
- assert(NULL != node);
- mem_release(node->contents);
- if(node->left) mem_release(node->left);
- if(node->right) mem_release(node->right);
+ rbt_node_t* node = (rbt_node_t*) v_node;
- if(node){
- mem_release(node->contents);
- if(node->left) mem_release(node->left);
- if(node->right) mem_release(node->right);
- }
++ assert(NULL != node);
++ mem_release(node->contents);
++ if(node->left) mem_release(node->left);
++ if(node->right) mem_release(node->right);
}
+ #ifndef TESTING
+ static
+ #endif
rbt_node_t* rbt_node_new(void* contents){
- rbt_node_t* node = mem_allocate(sizeof(rbt_node_t), &rbt_node_free);
- node->left = NULL;
- node->right = NULL;
- node->parent = NULL;
- node->contents = contents;
- node->color = RED;
- return node;
+ rbt_node_t* node = mem_allocate(sizeof(rbt_node_t), &rbt_node_free);
+ node->left = NULL;
+ node->right = NULL;
+ node->parent = NULL;
+ node->contents = contents;
+ node->color = RED;
+ return node;
}
/* ---------------------------------------- */
/* informational / querying functions */
/* ---------------------------------------- */
-
+ #ifndef TESTING
+ static
+ #endif
rbt_color_t rbt_node_color(rbt_node_t* node){
- //leaves are NULL and black implicitly
- return (node ? node->color : BLACK);
+ //leaves are NULL and black implicitly
+ return (node ? node->color : BLACK);
}
static rbt_node_t* rbt_lookup_node(rbt_t* tree, rbt_node_t* node, void* value){
}
static int rbt_count(rbt_node_t* node){
- return (!node ? 0 : (1 + rbt_count(node->left) + rbt_count(node->right)));
+ return (!node ? 0 : (1 + rbt_count(node->left) + rbt_count(node->right)));
}
- int rbt_count_nodes(rbt_t* tree){
+
+ int rbt_size(rbt_t* tree){
- return rbt_count(tree->root);
+ return rbt_count(tree->root);
}
-
/* ----------------------------------------- */
/* generally helpful tree manipulation */
/* ----------------------------------------- */
} direction_t;
static void rbt_rotate(rbt_t* tree, rbt_node_t* node, direction_t direction){
- rbt_node_t* edon = (direction == LEFT) ? node->right : node->left;
- assert(NULL != edon);
- rbt_node_t** edon_side = (direction == LEFT ? &(edon->left) : &(edon->right));
- rbt_node_t** node_side = (direction == LEFT ? &(node->right) : &(node->left));
- rbt_node_replace(tree, node, edon);
- *node_side = *edon_side; //safe to overwrite; points to edon
- if(*edon_side) (*edon_side)->parent = node;
- *edon_side = node;
- node->parent = edon;
+ rbt_node_t* edon = (direction == LEFT) ? node->right : node->left;
- if(edon){
- rbt_node_t** edon_side = (direction == LEFT ? &(edon->left) : &(edon->right));
- rbt_node_t** node_side = (direction == LEFT ? &(node->right) : &(node->left));
- rbt_node_replace(tree, node, edon);
- *node_side = *edon_side; //safe to overwrite; points to edon
- if(*edon_side) (*edon_side)->parent = node;
- *edon_side = node;
- node->parent = edon;
- } /* else rotation isn't allowed */
++ assert(NULL != edon);
++ rbt_node_t** edon_side = (direction == LEFT ? &(edon->left) : &(edon->right));
++ rbt_node_t** node_side = (direction == LEFT ? &(node->right) : &(node->left));
++ rbt_node_replace(tree, node, edon);
++ *node_side = *edon_side; //safe to overwrite; points to edon
++ if(*edon_side) (*edon_side)->parent = node;
++ *edon_side = node;
++ node->parent = edon;
}
/* -------------------- */
static void rbt_ins_rebalance(rbt_t* tree, rbt_node_t* node, direction_t heavy_side){
- rbt_node_t* parent = node->parent;
- assert(NULL != parent);
- rbt_node_t* grandparent = parent->parent;
- rbt_rotate(tree, grandparent, (heavy_side == LEFT ? RIGHT : LEFT));
- parent->color = BLACK;
- grandparent->color = RED;
+ rbt_node_t* parent = node->parent;
- rbt_node_t* grandparent = (parent ? parent->parent : NULL);
++ assert(NULL != parent);
++ rbt_node_t* grandparent = parent->parent;
+ rbt_rotate(tree, grandparent, (heavy_side == LEFT ? RIGHT : LEFT));
+ parent->color = BLACK;
+ grandparent->color = RED;
}
static void rbt_ins_recolor(rbt_t* tree, rbt_node_t* node){
}
rbt_node_t* rbt_insert(rbt_t* tree, void* value){
- rbt_node_t* new_node = rbt_node_new(value);
- rbt_insert_node(tree, new_node, tree->root);
- return new_node;
+ rbt_node_t* new_node = rbt_node_new(value);
+ rbt_insert_node(tree, new_node, tree->root);
+ return new_node;
}
--
/* ------------------- */
/* removal code */
/* ------------------- */
//node has a count -1 of black nodes to leaves relative to the rest of the tree
static void rbt_del_rebalance(rbt_t* tree, rbt_node_t* node){
- rbt_node_t* parent = node->parent;
- if(parent){
- direction_t node_side = (node == parent->left ? LEFT : RIGHT);
- rbt_node_t* sib = (node_side == LEFT ? parent->right : parent->left);
- assert(NULL != sib);
- //nibling: gender neutral term for niece or nephew.
- rbt_node_t* inside_nibling = node_side == LEFT ? sib->left : sib->right;
- rbt_node_t* outside_nibling = node_side == LEFT ? sib->right : sib->left;
- if(RED == rbt_node_color(sib)){
- //rotate so sib is black & recurse w/ new scenario
- rbt_rotate(tree, parent, node_side);
- parent->color = RED;
- sib->color = BLACK;
- rbt_del_rebalance(tree, node);
- }else if(BLACK == rbt_node_color(inside_nibling) && BLACK == rbt_node_color(outside_nibling)){
- //both niblings are black ; can paint sib red & rebalance on parent
- sib->color = RED;
- if(RED == rbt_node_color(parent)) parent->color = BLACK;
- else rbt_del_rebalance(tree, parent);
- }else if(BLACK == rbt_node_color(outside_nibling)){
- //convert "inside" case to "outside" case & recurse w/ new scenario
- rbt_rotate(tree, sib, (node_side == LEFT ? RIGHT : LEFT));
- sib->color = RED;
- inside_nibling->color = BLACK;
- rbt_del_rebalance(tree, node);
- }else{
- rbt_rotate(tree, parent, node_side);
- sib->color = parent->color;
- parent->color = BLACK;
- outside_nibling->color = BLACK;
- }
- }
+ rbt_node_t* parent = node->parent;
+ if(parent){
+ direction_t node_side = (node == parent->left ? LEFT : RIGHT);
+ rbt_node_t* sib = (node_side == LEFT ? parent->right : parent->left);
++ assert(NULL != sib);
+ //nibling: gender neutral term for niece or nephew.
- rbt_node_t* inside_nibling = sib ? (node_side == LEFT ? sib->left : sib->right) : NULL;
- rbt_node_t* outside_nibling = sib ? (node_side == LEFT ? sib->right : sib->left) : NULL;
++ rbt_node_t* inside_nibling = node_side == LEFT ? sib->left : sib->right;
++ rbt_node_t* outside_nibling = node_side == LEFT ? sib->right : sib->left;
+ if(RED == rbt_node_color(sib)){
+ //rotate so sib is black & recurse w/ new scenario
+ rbt_rotate(tree, parent, node_side);
+ parent->color = RED;
+ sib->color = BLACK;
+ rbt_del_rebalance(tree, node);
+ }else if(BLACK == rbt_node_color(inside_nibling) && BLACK == rbt_node_color(outside_nibling)){
+ //both niblings are black ; can paint sib red & rebalance on parent
+ sib->color = RED;
+ if(RED == rbt_node_color(parent)) parent->color = BLACK;
+ else rbt_del_rebalance(tree, parent);
+ }else if(BLACK == rbt_node_color(outside_nibling)){
+ //convert "inside" case to "outside" case & recurse w/ new scenario
+ rbt_rotate(tree, sib, (node_side == LEFT ? RIGHT : LEFT));
+ sib->color = RED;
+ inside_nibling->color = BLACK;
+ rbt_del_rebalance(tree, node);
+ }else{
+ rbt_rotate(tree, parent, node_side);
+ sib->color = parent->color;
+ parent->color = BLACK;
+ outside_nibling->color = BLACK;
+ }
- }else{
- node->color = BLACK; //TODO: verify this is necessary
+ }
}
static void rbt_delete_node(rbt_t* tree, rbt_node_t* node){