void make_balance_after_insert(ptr_rbnode node) { //case 1 : root node if (node->parent == NULL) { node->color = BLACK; return; } //case 2 : parent is black if (node->parent->color == BLACK) { return; //nothing to do } //now it is guaranteed that node has grandparent //case 3 : p and u = red, g = black ptr_rbnode g = get_grandparent(node), u = get_uncle(node), p = node->parent; assert(g); if (p->color == RED && u->color == RED && g->color == BLACK) { p->color = BLACK; u->color = BLACK; g->color = RED; make_balance_after_insert(g); /* this recursive operation will take O(log N) in worst case and O(1) in average case because the time complexity distribution would have a form of geometric distribution. */ return; } //case 4,5 : p = red, u = black, g = black; -> guaranteed //if node, p and g is not on a line, rotate //case 4 would be changed into case 5 assert(p->color == RED && u->color == BLACK && g->color == BLACK); if (g->left == p && p->right == node) { rotate_left(p); node = node->left; //for case 5 g = get_grandparent(node), u = get_uncle(node), p = node->parent; } else if (g->right == p && p->left == node) { rotate_right(p); // for case 5 g = get_grandparent(node), u = get_uncle(node), p = node->parent; node = node->right; } g = get_grandparent(node), u = get_uncle(node), p = node->parent; //case 5 assert((p->left == node && g->left == p) || (p->right == node && g->right == p)); p->color = BLACK; g->color = RED; if (p->left == node) { rotate_right(g); } else { rotate_left(g); } }
/* W. 2+3) Parent of node must be black, otherwise recolor and flush */ static void insert_check_2 (DLRBT_Tree *tree, DLRBT_Node *node) { /* if the parent is not black, we need to change that... */ if (node && node->parent && node->parent->tree_col) { DLRBT_Node *unc= get_uncle(node); /* if uncle and parent are both red, need to change them to black and make * the parent black in order to satisfy the criteria of each node having the * same number of black nodes to its leaves */ if (unc && unc->tree_col) { DLRBT_Node *gp= get_grandparent(node); /* make the n-1 generation nodes black */ node->parent->tree_col= unc->tree_col= DLRBT_BLACK; /* - make the grandparent red, so that we maintain alternating red/black property * (it must exist, so no need to check for NULL here), * - as the grandparent may now cause inconsistencies with the rest of the tree, * we must flush up the tree and perform checks/rebalancing/repainting, using the * grandparent as the node of interest */ gp->tree_col= DLRBT_RED; insert_check_1(tree, gp); } else { /* we've got an unbalanced branch going down the grandparent to the parent, * so need to perform some rotations to re-balance the tree */ insert_check_3(tree, node); } } }