static void recolor(rbtree_t *tree, rbtree_node_t *parent, rbtree_node_t *node) { rbtree_node_t *sibling; while(is_black(node) && node != tree->root) { int left = (node == parent->child[LEFT]); sibling = parent->child[left]; if(is_red(sibling)) { set_black(sibling); set_red(parent); rbtree_rotate(tree, parent, left); sibling = parent->child[left]; } if(is_black(sibling->child[LEFT]) && is_black(sibling->child[RIGHT])) { set_red(sibling); node = parent; parent = get_parent(node); } else { if(is_black(sibling->child[left])) { set_black(sibling->child[!left]); set_red(sibling); rbtree_rotate(tree, sibling, !left); sibling = parent->child[left]; } if(is_black(parent)) set_black(sibling); else set_red(sibling); set_black(parent); set_black(sibling->child[left]); rbtree_rotate(tree, parent, left); node = tree->root; } } if(node != NULL) set_black(node); }
/** * Rebalance the rbtree, so that no more than two RBTREE_COLOR_RED * nodes appear in a row. */ static void c_rbtree_rebalance(struct c_rbtree_entry *node) { struct c_rbtree_entry *parent, *grandfather, *uncle; while (node) { parent = node->rb_parent; grandfather = (parent ? parent->rb_parent : NULL); if (grandfather && parent == grandfather->rb_left) uncle = grandfather->rb_right; else if (grandfather && parent == grandfather->rb_right) uncle = grandfather->rb_left; /* If parent is black and we are red, we're fine. */ if (parent->rb_color == RBTREE_COLOR_BLACK) return; if (uncle && uncle->rb_color == RBTREE_COLOR_RED) { parent->rb_color = RBTREE_COLOR_BLACK; uncle->rb_color = RBTREE_COLOR_BLACK; grandfather->rb_color = RBTREE_COLOR_RED; node = grandfather; } else { if (node == parent->rb_right && parent == grandfather->rb_left) { rbtree_rotate(parent); node = node->rb_left; parent = node ? node->rb_parent : NULL; grandfather = parent ? parent->rb_parent : NULL; } else if (node == parent->rb_left && parent == grandfather->rb_right) { rbtree_rotate(parent); node = node->rb_right; parent = node ? node->rb_parent : NULL; grandfather = parent ? parent->rb_parent : NULL; } node->rb_parent->rb_color = RBTREE_COLOR_BLACK; grandfather->rb_color = RBTREE_COLOR_RED; if (node == parent->rb_left && parent == grandfather->rb_left) rbtree_rotate(grandfather); else if (node == parent->rb_right && parent == grandfather->rb_right) rbtree_rotate(grandfather); return; } } return; }