Ejemplo n.º 1
0
Archivo: rbt.c Proyecto: 1587/ltp
void rbtree_remove_fixup(rb_tree * tree, rb_node * node)
{
	rb_node *curr_node = node;
	rb_node *sibling;

	while (curr_node != tree->root && curr_node->color == black) {
		/* Get a pointer to the current node's sibling (notice
		 * that the node's parent must exist, since the node
		 * is not the root).
		 */
		if (curr_node == curr_node->parent->left) {
			/* If the current node is a left child, its
			 * sibling is the right child of the parent.
			 */
			sibling = curr_node->parent->right;

			/* Check the sibling's color. Notice that NULL
			 * nodes are treated as if they are colored
			 * black.
			 */
			if (sibling && sibling->color == red) {
				/* In case the sibling is red, color
				 * it black and rotate.  Then color
				 * the parent red (the grandparent is
				 * now black)
				 */
				sibling->color = black;
				curr_node->parent->color = red;
				rbtree_rotate_left(tree, curr_node->parent);
				sibling = curr_node->parent->right;
			}

			if (sibling &&
			    (!(sibling->left) || sibling->left->color == black)
			    && (!(sibling->right)
				|| sibling->right->color == black)) {
				/* If the sibling has two black
				 * children, color it red
				 */
				sibling->color = red;
				if (curr_node->parent->color == red) {
					/* If the parent is red, we
					 * can safely color it black
					 * and terminate the fix
					 * process.
					 */
					curr_node->parent->color = black;
					/* In order to stop the while loop */
					curr_node = tree->root;
				} else {
					/* The black depth of the
					 * entire sub-tree rooted at
					 * the parent is now too small
					 * - fix it up recursively.
					 */
					curr_node = curr_node->parent;
				}
			} else {
				if (!sibling) {
					/* Take special care of the
					 * case of a NULL sibling
					 */
					if (curr_node->parent->color == red) {
						curr_node->parent->color =
						    black;
						/* In order to stop
						 * the while loop */
						curr_node = tree->root;
					} else {
						curr_node = curr_node->parent;
					}
				} else {
					/* In this case, at least one
					 * of the sibling's children
					 * is red.  It is therfore
					 * obvious that the sibling
					 * itself is black.
					 */
					if (sibling->right
					    && sibling->right->color == red) {
						/* If the right child
						 * of the sibling is
						 * red, color it black
						 * and rotate around
						 * the current parent.
						 */
						sibling->right->color = black;
						rbtree_rotate_left(tree,
								   curr_node->
								   parent);
					} else {
						/* If the left child
						 * of the sibling is
						 * red, rotate around
						 * the sibling, then
						 * rotate around the
						 * new sibling of our
						 * current node.
						 */
						rbtree_rotate_right(tree,
								    sibling);
						sibling =
						    curr_node->parent->right;
						rbtree_rotate_left(tree,
								   sibling);
					}

					/* It is now safe to color the
					 * parent black and to
					 * terminate the fix process.
					 */
					if (curr_node->parent->parent)
						curr_node->parent->parent->
						    color =
						    curr_node->parent->color;
					curr_node->parent->color = black;
					/* In order to stop the while loop */
					curr_node = tree->root;
				}
			}
		} else {
			/* If the current node is a right child, its
			 * sibling is the left child of the parent.
			 */
			sibling = curr_node->parent->left;

			/* Check the sibling's color. Notice that NULL
			 * nodes are treated as if they are colored
			 * black.
			 */
			if (sibling && sibling->color == red) {
				/* In case the sibling is red, color
				 * it black and rotate.  Then color
				 * the parent red (the grandparent is
				 * now black).
				 */
				sibling->color = black;
				curr_node->parent->color = red;
				rbtree_rotate_right(tree, curr_node->parent);

				sibling = curr_node->parent->left;
			}

			if (sibling &&
			    (!(sibling->left) || sibling->left->color == black)
			    && (!(sibling->right)
				|| sibling->right->color == black)) {
				/* If the sibling has two black children, color it red */
				sibling->color = red;
				if (curr_node->parent->color == red) {
					/* If the parent is red, we
					 * can safely color it black
					 * and terminate the fix-up
					 * process.
					 */
					curr_node->parent->color = black;
					/* In order to stop the while
					 * loop
					 */
					curr_node = tree->root;
				} else {
					/* The black depth of the
					 * entire sub-tree rooted at
					 * the parent is now too small
					 * - fix it up recursively.
					 */
					curr_node = curr_node->parent;
				}
			} else {
				if (!sibling) {
					/* Take special care of the
					 * case of a NULL sibling */
					if (curr_node->parent->color == red) {
						curr_node->parent->color =
						    black;
						/* In order to stop
						 * the while loop */
						curr_node = tree->root;
					} else {
						curr_node = curr_node->parent;
					}
				} else {
					/* In this case, at least one
					 * of the sibling's children is
					 * red.  It is therfore obvious
					 * that the sibling itself is
					 * black.
					 */
					if (sibling->left
					    && sibling->left->color == red) {
						/* If the left child
						 * of the sibling is
						 * red, color it black
						 * and rotate around
						 * the current parent
						 */
						sibling->left->color = black;
						rbtree_rotate_right(tree,
								    curr_node->
								    parent);
					} else {
						/* If the right child
						 * of the sibling is
						 * red, rotate around
						 * the sibling, then
						 * rotate around the
						 * new sibling of our
						 * current node
						 */
						rbtree_rotate_left(tree,
								   sibling);
						sibling =
						    curr_node->parent->left;
						rbtree_rotate_right(tree,
								    sibling);
					}

					/* It is now safe to color the
					 * parent black and to
					 * terminate the fix process.
					 */
					if (curr_node->parent->parent)
						curr_node->parent->parent->
						    color =
						    curr_node->parent->color;
					curr_node->parent->color = black;
					/* In order to stop the while loop */
					curr_node = tree->root;
				}
			}
		}
	}

	/* The root can always be colored black */
	curr_node->color = black;
}
Ejemplo n.º 2
0
Archivo: rbt.c Proyecto: 1587/ltp
void rbtree_insert_fixup(rb_tree * tree, rb_node * node)
{
	/* Fix the red-black propreties. We may have inserted a red
	 * leaf as the child of a red parent - so we have to fix the
	 * coloring of the parent recursively.
	 */
	rb_node *curr_node = node;
	rb_node *grandparent;
	rb_node *uncle;

	assert(node && node->color == red);

	while (curr_node != tree->root && curr_node->parent->color == red) {
		/* Get a pointer to the current node's grandparent
		 * (the root is always black, so the red parent must
		 * have a parent).
		 */

		grandparent = curr_node->parent->parent;

		if (curr_node->parent == grandparent->left) {
			/* If the red parent is a left child, the
			 * uncle is the right child of the grandparent.
			 */
			uncle = grandparent->right;

			if (uncle && uncle->color == red) {

				/* If both parent and uncle are red,
				 * color them black and color the
				 * grandparent red. In case of a NULL
				 * uncle, treat it as a black node
				 */
				curr_node->parent->color = black;
				uncle->color = black;
				grandparent->color = red;

				/* Move to the grandparent */
				curr_node = grandparent;
			} else {
				/* Make sure the current node is a
				 * right child. If not, left-rotate the
				 * parent's sub-tree so the parent
				 * becomes the right child of the
				 * current node (see _rotate_left).
				 */
				if (curr_node == curr_node->parent->right) {
					curr_node = curr_node->parent;
					rbtree_rotate_left(tree, curr_node);
				}

				/* Color the parent black and the
				 * grandparent red
				 */
				curr_node->parent->color = black;
				grandparent->color = red;

				/* Right-rotate the grandparent's
				 * sub-tree
				 */
				rbtree_rotate_right(tree, grandparent);
			}
		} else {
			/* If the red parent is a right child, the
			 * uncle is the left child of the grandparent.
			 */
			uncle = grandparent->left;

			if (uncle && uncle->color == red) {
				/* If both parent and uncle are red,
				 * color them black and color the
				 * grandparent red. In case of a NULL
				 * uncle, treat it as a black node
				 */
				curr_node->parent->color = black;
				uncle->color = black;
				grandparent->color = red;

				/* Move to the grandparent */
				curr_node = grandparent;
			} else {
				/* Make sure the current node is a
				 * left child. If not, right-rotate
				 * the parent's sub-tree so the parent
				 * becomes the left child of the
				 * current node.
				 */
				if (curr_node == curr_node->parent->left) {
					curr_node = curr_node->parent;
					rbtree_rotate_right(tree, curr_node);
				}

				/* Color the parent black and the
				 * grandparent red
				 */
				curr_node->parent->color = black;
				grandparent->color = red;

				/* Left-rotate the grandparent's
				 * sub-tree
				 */
				rbtree_rotate_left(tree, grandparent);
			}
		}
	}

	/* Make sure that the root is black */
	tree->root->color = black;
}
Ejemplo n.º 3
0
/*! 
 * Fix-up the red-black tree properties after a removal operation
 *
 * \param tree The tree
 *
 * \param node The child of the node that has just been removed from the tree
 */
void rbtree_remove_fixup(rbtree_t * tree, rbnode_t * node)
    {
    rbnode_t * curr_node = node;
    rbnode_t * sibling;

    while (curr_node != tree->root && curr_node->color == RB_BLACK)
        {
        /* Get a pointer to the current node's sibling (notice that the node's
         * parent must exist, since the node is not the root).
         */
        if (curr_node == curr_node->parent->left)
            {
            /* If the current node is a left child, its sibling is the right
             * child of the parent.
             */
            sibling = curr_node->parent->right;

            /* Check the sibling's color. Notice that NULL nodes are treated
             * as if they are colored black.
             */
            if (sibling && sibling->color == RB_RED)
                {
                /* In case the sibling is red, color it black and rotate.
                 * Then color the parent red (and the grandparent is now black).
                 */
                sibling->color = RB_BLACK;
                curr_node->parent->color = RB_RED;
                rbtree_rotate_left(tree, curr_node->parent);
                sibling = curr_node->parent->right;
                }

            if (sibling &&
                    (!(sibling->left) || sibling->left->color == RB_BLACK) &&
                    (!(sibling->right) || sibling->right->color == RB_BLACK))
                {
                /* If the sibling has two black children, color it red */
                sibling->color = RB_RED;
                if (curr_node->parent->color == RB_RED)
                    {
                    /* 
                     * If the parent is red, we can safely color it black
                     * and terminate the fix-up process.
                     */
                    curr_node->parent->color = RB_BLACK;
                    
                    /* In order to stop the while loop */
                    curr_node = tree->root;      
                    }
                else
                    {
                    /*
                     * The black depth of the entire sub-tree rooted at the parent is
                     * now too small - fix it up recursively.
                     */
                    curr_node = curr_node->parent;
                    }
                }
            else
                {
                if (!sibling)
                    {
                    /* Take special care of the case of a NULL sibling */
                    if (curr_node->parent->color == RB_RED)
                        {
                        curr_node->parent->color = RB_BLACK;
                        
                        /* In order to stop the while loop */
                        curr_node = tree->root;    
                        }
                    else
                        {
                        curr_node = curr_node->parent;
                        }
                    }
                else
                    {
                    /* In this case, at least one of the sibling's children is red.
                     * It is therfore obvious that the sibling itself is black.
                     */
                    if (sibling->right && sibling->right->color == RB_RED)
                        {
                        /* 
                         * If the right child of the sibling is red, color it 
                         * black and rotate around the current parent.
                         */
                        sibling->right->color = RB_BLACK;
                        rbtree_rotate_left(tree, curr_node->parent);
                        }
                    else
                        {
                        /* If the left child of the sibling is red, rotate
                         * around the sibling, then rotate around the new
                         * sibling of our current node.
                         */
                        rbtree_rotate_right(tree, sibling);
                        sibling = curr_node->parent->right;
                        rbtree_rotate_left(tree, sibling);
                        }

                    /* 
                     * It is now safe to color the parent black and 
                     * to terminate the fix-up process.
                     */
                    if (curr_node->parent->parent)
                        curr_node->parent->parent->color = 
                            curr_node->parent->color;

                    curr_node->parent->color = RB_BLACK;
                    
                    /* In order to stop the while loop */
                    curr_node = tree->root;     
                    }
                }
            }
        else
            {
            /* 
             * If the current node is a right child, its sibling is the left
             * child of the parent.
             */
            sibling = curr_node->parent->left;

            /* 
             * Check the sibling's color. Notice that NULL nodes are treated
             * as if they are colored black.
             */
            if (sibling && sibling->color == RB_RED)
                {
                /* 
                 * In case the sibling is red, color it black and rotate.
                 * Then color the parent red (and the grandparent is now black).
                 */
                sibling->color = RB_BLACK;
                curr_node->parent->color = RB_RED;
                
                rbtree_rotate_right(tree, curr_node->parent);

                sibling = curr_node->parent->left;
                }

            if (sibling &&
                (!(sibling->left) || sibling->left->color == RB_BLACK) &&
                (!(sibling->right) || sibling->right->color == RB_BLACK))
                {
                /* If the sibling has two black children, color it red */
                sibling->color = RB_RED;
                if (curr_node->parent->color == RB_RED)
                    {
                    /* 
                     * If the parent is red, we can safely color it black 
                     * and terminate the fix-up process.
                     */
                    curr_node->parent->color = RB_BLACK;
                    
                    /* In order to stop the while loop */
                    curr_node = tree->root;      
                    }
                else
                    {
                    /* 
                     * The black depth of the entire sub-tree rooted at 
                     * the parent is now too small - fix it up recursively.
                     */
                    curr_node = curr_node->parent;
                    }
                }
            else
                {
                if (!sibling)
                    {
                    /* Take special care of the case of a NULL sibling */
                    if (curr_node->parent->color == RB_RED)
                        {
                        curr_node->parent->color = RB_BLACK;
                        
                        /* In order to stop the while loop */
                        curr_node = tree->root;    
                        }
                    else
                        {
                        curr_node = curr_node->parent;
                        }
                    }
                else
                    {
                    /* In this case, at least one of the sibling's children is red.
                     * It is therfore obvious that the sibling itself is black.
                     */
                    if (sibling->left && sibling->left->color == RB_RED)
                        {
                        /* If the left child of the sibling is red, color it 
                         * black and rotate around the current parent
                         */
                        sibling->left->color = RB_BLACK;
                        rbtree_rotate_right(tree, curr_node->parent);
                        }
                    else
                        {
                        /* 
                         * If the right child of the sibling is red, rotate 
                         * around the sibling, then rotate around the new 
                         * sibling of our current node.
                         */
                        rbtree_rotate_left(tree, sibling);
                        sibling = curr_node->parent->left;
                        rbtree_rotate_right(tree, sibling);
                        }

                    /* 
                     * It is now safe to color the parent black and to 
                     * terminate the fix-up process.
                     */
                    if (curr_node->parent->parent)
                        curr_node->parent->parent->color = 
                                        curr_node->parent->color;
                    
                    curr_node->parent->color = RB_BLACK;
                    
                    /* In order to stop the while loop */
                    curr_node = tree->root;       
                    }
                }
            }
        }

    /* The root can always be colored black */
    curr_node->color = RB_BLACK;
    }
Ejemplo n.º 4
0
static void
rbtree_insert_fixup(rbtree_t *rbtree, rbnode_t *node)
{
    rbnode_t	*uncle;

    /* While not at the root and need fixing... */
    while (node != rbtree->root && node->parent->color == RED) {
        /* If our parent is left child of our grandparent... */
        if (node->parent == node->parent->parent->left) {
            uncle = node->parent->parent->right;

            /* If our uncle is red... */
            if (uncle->color == RED) {
                /* Paint the parent and the uncle black... */
                node->parent->color = BLACK;
                uncle->color = BLACK;

                /* And the grandparent red... */
                node->parent->parent->color = RED;

                /* And continue fixing the grandparent */
                node = node->parent->parent;
            } else {				/* Our uncle is black... */
                /* Are we the right child? */
                if (node == node->parent->right) {
                    node = node->parent;
                    rbtree_rotate_left(rbtree, node);
                }
                /* Now we're the left child, repaint and rotate... */
                node->parent->color = BLACK;
                node->parent->parent->color = RED;
                rbtree_rotate_right(rbtree, node->parent->parent);
            }
        } else {
            uncle = node->parent->parent->left;

            /* If our uncle is red... */
            if (uncle->color == RED) {
                /* Paint the parent and the uncle black... */
                node->parent->color = BLACK;
                uncle->color = BLACK;

                /* And the grandparent red... */
                node->parent->parent->color = RED;

                /* And continue fixing the grandparent */
                node = node->parent->parent;
            } else {				/* Our uncle is black... */
                /* Are we the right child? */
                if (node == node->parent->left) {
                    node = node->parent;
                    rbtree_rotate_right(rbtree, node);
                }
                /* Now we're the right child, repaint and rotate... */
                node->parent->color = BLACK;
                node->parent->parent->color = RED;
                rbtree_rotate_left(rbtree, node->parent->parent);
            }
        }
    }
    rbtree->root->color = BLACK;
}
Ejemplo n.º 5
0
/*!
 * Fix-up the red-black tree properties after an insertion operation
 * so it maintains the red-black properties.
 *
 * \param tree The tree
 *
 * \param node The node that has just been inserted to the tree
 *
 * \pre The color of node must be red
 */
void rbtree_insert_fixup
    (
    rbtree_t * tree,
    rbnode_t * node
    )
    {
    /*
     * Fix the red-black propreties: we may have inserted a red
     * leaf as the child of a red parent - so we have to fix the
     * coloring of the parent recursively.
     */
    rbnode_t * curr_node = node;
    rbnode_t * grandparent;
    rbnode_t *uncle;

    ASSERT(node && node->color == RB_RED);

    while (curr_node != tree->root &&
            curr_node->parent->color == RB_RED)
        {
        /*
         * Get a pointer to the current node's grandparent
         * (notice the root is always black, so the red
         * parent must have a parent).
         */
        grandparent = curr_node->parent->parent;

        if (curr_node->parent == grandparent->left)
            {
            /* If the red parent is a left child, the uncle is the right child of
            * the grandparent.
            */
            uncle = grandparent->right;

            if (uncle && uncle->color == RB_RED)
                {
                /* If both parent and uncle are red, color them black and color the
                 * grandparent red.
                 * In case of a NULL uncle, we treat it as a black node.
                 */
                curr_node->parent->color = RB_BLACK;
                uncle->color = RB_BLACK;
                grandparent->color = RB_RED;

                /* Move to the grandparent */
                curr_node = grandparent;
                }
            else
                {
                /* Make sure the current node is a right child. If not, left-rotate
                 * the parent's sub-tree so the parent becomes the right child of the
                 * current node (see _rotate_left).
                 */
                if (curr_node == curr_node->parent->right)
                    {
                    curr_node = curr_node->parent;
                    rbtree_rotate_left(tree, curr_node);
                    }

                /* Color the parent black and the grandparent red */
                curr_node->parent->color = RB_BLACK;
                grandparent->color = RB_RED;

                /* Right-rotate the grandparent's sub-tree */
                rbtree_rotate_right(tree, grandparent);
                }
            }
        else
            {
            /* If the red parent is a right child, the uncle is the left child of
            * the grandparent.
            */
            uncle = grandparent->left;

            if (uncle && uncle->color == RB_RED)
                {
                /* If both parent and uncle are red, color them black and color the
                 * grandparent red.
                 * In case of a NULL uncle, we treat it as a black node.
                 */
                curr_node->parent->color = RB_BLACK;
                uncle->color = RB_BLACK;
                grandparent->color = RB_RED;

                /* Move to the grandparent */
                curr_node = grandparent;
                }
            else
                {
                /* Make sure the current node is a left child. If not, right-rotate
                 * the parent's sub-tree so the parent becomes the left child of the
                 * current node.
                 */
                if (curr_node == curr_node->parent->left)
                    {
                    curr_node = curr_node->parent;
                    rbtree_rotate_right(tree, curr_node);
                    }

                /* Color the parent black and the grandparent red */
                curr_node->parent->color = RB_BLACK;
                grandparent->color = RB_RED;

                /* Left-rotate the grandparent's sub-tree */
                rbtree_rotate_left(tree, grandparent);
                }
            }
        }

    /* Make sure that the root is black */
    tree->root->color = RB_BLACK;
    }