/* * Operations INSERT and DELETE, when run on a tree with n keys, * take O(logN) time.Because they modify the tree, the result * may violate the red-black properties.To restore these properties, * we must change the colors of some of the nodes in the tree * and also change the pointer structure. */ static void interval_insert_color(struct interval_node *node, struct interval_node **root) { struct interval_node *parent, *gparent; while ((parent = node->in_parent) && node_is_red(parent)) { gparent = parent->in_parent; /* Parent is RED, so gparent must not be NULL */ if (node_is_left_child(parent)) { struct interval_node *uncle; uncle = gparent->in_right; if (uncle && node_is_red(uncle)) { uncle->in_color = INTERVAL_BLACK; parent->in_color = INTERVAL_BLACK; gparent->in_color = INTERVAL_RED; node = gparent; continue; } if (parent->in_right == node) { __rotate_left(parent, root); interval_swap(node, parent); } parent->in_color = INTERVAL_BLACK; gparent->in_color = INTERVAL_RED; __rotate_right(gparent, root); } else { struct interval_node *uncle; uncle = gparent->in_left; if (uncle && node_is_red(uncle)) { uncle->in_color = INTERVAL_BLACK; parent->in_color = INTERVAL_BLACK; gparent->in_color = INTERVAL_RED; node = gparent; continue; } if (node_is_left_child(node)) { __rotate_right(parent, root); interval_swap(node, parent); } parent->in_color = INTERVAL_BLACK; gparent->in_color = INTERVAL_RED; __rotate_left(gparent, root); } } (*root)->in_color = INTERVAL_BLACK; }
/* The left rotation "pivots" around the link from node to node->right, and * - node will be linked to node->right's left child, and * - node->right's left child will be linked to node's right child. */ static void __rotate_left(struct interval_node *node, struct interval_node **root) { struct interval_node *right = node->in_right; struct interval_node *parent = node->in_parent; node->in_right = right->in_left; if (node->in_right) right->in_left->in_parent = node; right->in_left = node; right->in_parent = parent; if (parent) { if (node_is_left_child(node)) parent->in_left = right; else parent->in_right = right; } else { *root = right; } node->in_parent = right; /* update max_high for node and right */ __rotate_change_maxhigh(node, right); }
static struct interval_node *interval_prev(struct interval_node *node) { if (!node) return NULL; if (node->in_left) return interval_last(node->in_left); while (node->in_parent && node_is_left_child(node)) node = node->in_parent; return node->in_parent; }
static struct interval_node *interval_prev(struct interval_node *node) { ENTRY; if (!node) RETURN(NULL); if (node->in_left) RETURN(interval_last(node->in_left)); while (node->in_parent && node_is_left_child(node)) node = node->in_parent; RETURN(node->in_parent); }
void interval_erase(struct interval_node *node, struct interval_node **root) { struct interval_node *child, *parent; int color; LASSERT(interval_is_intree(node)); node->in_intree = 0; if (!node->in_left) { child = node->in_right; } else if (!node->in_right) { child = node->in_left; } else { /* Both left and right child are not NULL */ struct interval_node *old = node; node = interval_next(node); child = node->in_right; parent = node->in_parent; color = node->in_color; if (child) child->in_parent = parent; if (parent == old) parent->in_right = child; else parent->in_left = child; node->in_color = old->in_color; node->in_right = old->in_right; node->in_left = old->in_left; node->in_parent = old->in_parent; if (old->in_parent) { if (node_is_left_child(old)) old->in_parent->in_left = node; else old->in_parent->in_right = node; } else { *root = node; } old->in_left->in_parent = node; if (old->in_right) old->in_right->in_parent = node; update_maxhigh(child ? : parent, node->in_max_high); update_maxhigh(node, old->in_max_high); if (parent == old) parent = node; goto color; } parent = node->in_parent; color = node->in_color; if (child) child->in_parent = parent; if (parent) { if (node_is_left_child(node)) parent->in_left = child; else parent->in_right = child; } else { *root = child; } update_maxhigh(child ? : parent, node->in_max_high); color: if (color == INTERVAL_BLACK) interval_erase_color(child, parent, root); }