Пример #1
0
static void __rb_erase_color(LPRB_NODE node, LPRB_NODE parent, LPRB_ROOT root)
{
	LPRB_NODE other;

	while ((!node || rb_is_black(node)) && node != root->rb_node)
	{
		if (parent->rb_left == node)
		{
			other = parent->rb_right;
			if (rb_is_red(other))
			{
				rb_set_black(other);
				rb_set_red(parent);
				__rb_rotate_left(parent, root);
				other = parent->rb_right;
			}
			if ((!other->rb_left || rb_is_black(other->rb_left)) &&
			    (!other->rb_right || rb_is_black(other->rb_right)))
			{
				rb_set_red(other);
				node = parent;
				parent = rb_parent(node);
			}
			else
			{
				if (!other->rb_right || rb_is_black(other->rb_right))
				{
					rb_set_black(other->rb_left);
					rb_set_red(other);
					__rb_rotate_right(other, root);
					other = parent->rb_right;
				}
				rb_set_color(other, rb_color(parent));
				rb_set_black(parent);
				rb_set_black(other->rb_right);
				__rb_rotate_left(parent, root);
				node = root->rb_node;
				break;
			}
		}
		else
		{
			other = parent->rb_left;
			if (rb_is_red(other))
			{
				rb_set_black(other);
				rb_set_red(parent);
				__rb_rotate_right(parent, root);
				other = parent->rb_left;
			}
			if ((!other->rb_left || rb_is_black(other->rb_left)) &&
			    (!other->rb_right || rb_is_black(other->rb_right)))
			{
				rb_set_red(other);
				node = parent;
				parent = rb_parent(node);
			}
			else
			{
				if (!other->rb_left || rb_is_black(other->rb_left))
				{
					rb_set_black(other->rb_right);
					rb_set_red(other);
					__rb_rotate_left(other, root);
					other = parent->rb_left;
				}
				rb_set_color(other, rb_color(parent));
				rb_set_black(parent);
				rb_set_black(other->rb_left);
				__rb_rotate_right(parent, root);
				node = root->rb_node;
				break;
			}
		}
	}
	if (node)
		rb_set_black(node);
}
Пример #2
0
static void __rb_erase_color(struct rb_node *node, struct rb_node *parent,
			     struct rb_root *root)
{
	struct rb_node *other;
	
	int pr_flag = 1;

	while ((!node || rb_is_black(node)) && node != root->rb_node)
	{
		if (parent->rb_left == node)
		{
			other = parent->rb_right;
			if (rb_is_red(other))
			{
				if (pr_flag)
				{
					pr_debug("对应情况1。\n");
					pr_flag = 0;
				}	
				
				rb_set_black(other);
				rb_set_red(parent);
				__rb_rotate_left(parent, root);
				other = parent->rb_right;
			}
			if ((!other->rb_left || rb_is_black(other->rb_left)) &&
			    (!other->rb_right || rb_is_black(other->rb_right)))
			{				
				if (pr_flag)
				{
					pr_debug("对应情况2。\n");
					pr_flag = 0;
				}	
				
				rb_set_red(other);
				node = parent;
				parent = rb_parent(node);
			}
			else
			{
				if (!other->rb_right || rb_is_black(other->rb_right))
				{
					if (pr_flag)
					{
						pr_debug("对应情况3。\n");
						pr_flag = 0;
					}						
					
					rb_set_black(other->rb_left);
					rb_set_red(other);
					__rb_rotate_right(other, root);
					other = parent->rb_right;
				}
				
				if (pr_flag)
				{
					pr_debug("对应情况4。\n");
					pr_flag = 0;
				}
				
				rb_set_color(other, rb_color(parent));
				rb_set_black(parent);
				rb_set_black(other->rb_right);
				__rb_rotate_left(parent, root);
				node = root->rb_node;
				break;
			}
		}
		else
		{
			other = parent->rb_left;
			if (rb_is_red(other))
			{
				if (pr_flag)
				{
					pr_debug("对应情况1(反)。\n");
					pr_flag = 0;
				}	
				
				rb_set_black(other);
				rb_set_red(parent);
				__rb_rotate_right(parent, root);
				other = parent->rb_left;
			}
			if ((!other->rb_left || rb_is_black(other->rb_left)) &&
			    (!other->rb_right || rb_is_black(other->rb_right)))
			{
				if (pr_flag)
				{
					pr_debug("对应情况2(反)。\n");
					pr_flag = 0;
				}	
				
				rb_set_red(other);
				node = parent;
				parent = rb_parent(node);
			}
			else
			{
				if (!other->rb_left || rb_is_black(other->rb_left))
				{
					if (pr_flag)
					{
						pr_debug("对应情况3(反)。\n");
						pr_flag = 0;
					}	
					
					
					rb_set_black(other->rb_right);
					rb_set_red(other);
					__rb_rotate_left(other, root);
					other = parent->rb_left;
				}
				
				if (pr_flag)
				{
					pr_debug("对应情况4(反)。\n");
					pr_flag = 0;
				}	
				
				rb_set_color(other, rb_color(parent));
				rb_set_black(parent);
				rb_set_black(other->rb_left);
				__rb_rotate_right(parent, root);
				node = root->rb_node;
				break;
			}
		}
	}
	
	if (pr_flag)
	{
		if (node && rb_is_red(node))	//红结点
		{
			pr_debug("对应情况S。\n");
		}
		else
		{
			pr_debug("对应情况?。\n");
		}
	}
	
	if (node) 		
		rb_set_black(node);
		

}
Пример #3
0
static void __rb_erase_color(struct rb_node *node, struct rb_node *parent,
			     struct rb_root *root)
{
	struct rb_node *other;

	while ((!node || rb_is_black(node)) && node != root->rb_node)
	{
		if (parent->rb_left == node)
		{
			other = parent->rb_right;
			if (rb_is_red(other))
			{
				rb_set_black(other);
				rb_set_red(parent);
				__rb_rotate_left(parent, root);
				other = parent->rb_right;
			}
			if ((!other->rb_left || rb_is_black(other->rb_left)) &&
			    (!other->rb_right || rb_is_black(other->rb_right)))
			{
				rb_set_red(other);
				node = parent;
				parent = rb_parent(node);
			}
			else
			{
				if (!other->rb_right || rb_is_black(other->rb_right))
				{
					struct rb_node *o_left;
					if ((o_left = other->rb_left))
						rb_set_black(o_left);
					rb_set_red(other);
					__rb_rotate_right(other, root);
					other = parent->rb_right;
				}
				rb_set_color(other, rb_color(parent));
				rb_set_black(parent);
				if (other->rb_right)
					rb_set_black(other->rb_right);
				__rb_rotate_left(parent, root);
				node = root->rb_node;
				break;
			}
		}
		else
		{
			other = parent->rb_left;
			if (rb_is_red(other))
			{
				rb_set_black(other);
				rb_set_red(parent);
				__rb_rotate_right(parent, root);
				other = parent->rb_left;
			}
			if ((!other->rb_left || rb_is_black(other->rb_left)) &&
			    (!other->rb_right || rb_is_black(other->rb_right)))
			{
				rb_set_red(other);
				node = parent;
				parent = rb_parent(node);
			}
			else
			{
				if (!other->rb_left || rb_is_black(other->rb_left))
				{
					register struct rb_node *o_right;
					if ((o_right = other->rb_right))
						rb_set_black(o_right);
					rb_set_red(other);
					__rb_rotate_left(other, root);
					other = parent->rb_left;
				}
				rb_set_color(other, rb_color(parent));
				rb_set_black(parent);
				if (other->rb_left)
					rb_set_black(other->rb_left);
				__rb_rotate_right(parent, root);
				node = root->rb_node;
				break;
			}
		}
	}
	if (node)
		rb_set_black(node);
}
Пример #4
0
static void rbtree_remove(char *node, char **tree)
{
    char *parent = rb_get_parent(node);
    char *left = rbtree_get_left(node);
    char *right = rbtree_get_right(node);
    char *next;
    int color;

    if (!left)
        next = right;
    else if (!right)
        next = left;
    else
        next = rbtree_first(right);

    if (parent)
        rb_set_child(next, parent, rbtree_get_left(parent) == node);
    else
        *tree = next;

    if (left && right) {
        color = rb_get_color(next);
        rb_set_color(rb_get_color(node), next);

        rb_set_left(left, next);
        rb_set_parent(next, left);

        if (next != right) {
            parent = rb_get_parent(next);
            rb_set_parent(rb_get_parent(node), next);

            node = rbtree_get_right(next);
            rb_set_left(node, parent);

            rb_set_right(right, next);
            rb_set_parent(next, right);
        } else {
            rb_set_parent(parent, next);
            parent = next;
            node = rbtree_get_right(next);
        }
    } else {
        color = rb_get_color(node);
        node = next;
    }
    /*
     * 'node' is now the sole successor's child and 'parent' its
     * new parent (since the successor can have been moved).
     */
    if (node)
        rb_set_parent(parent, node);

    /*
     * The 'easy' cases.
     */
    if (color == RB_RED)
        return;
    if (node && rb_is_red(node)) {
        rb_set_color(RB_BLACK, node);
        return;
    }

    do {
        if (node == *tree)
            break;

        if (node == rbtree_get_left(parent)) {
            char *sibling = rbtree_get_right(parent);

            if (rb_is_red(sibling)) {
                rb_set_color(RB_BLACK, sibling);
                rb_set_color(RB_RED, parent);
                rb_rotate_left(parent, tree);
                sibling = rbtree_get_right(parent);
            }
            if ((!rbtree_get_left(sibling)  || rb_is_black(rbtree_get_left(sibling))) &&
                (!rbtree_get_right(sibling) || rb_is_black(rbtree_get_right(sibling)))) {
                rb_set_color(RB_RED, sibling);
                node = parent;
                parent = rb_get_parent(parent);
                continue;
            }
            if (!rbtree_get_right(sibling) || rb_is_black(rbtree_get_right(sibling))) {
                rb_set_color(RB_BLACK, rbtree_get_left(sibling));
                rb_set_color(RB_RED, sibling);
                rb_rotate_right(sibling, tree);
                sibling = rbtree_get_right(parent);
            }
            rb_set_color(rb_get_color(parent), sibling);
            rb_set_color(RB_BLACK, parent);
            rb_set_color(RB_BLACK, rbtree_get_right(sibling));
            rb_rotate_left(parent, tree);
            node = *tree;
            break;
        } else {
            char *sibling = rbtree_get_left(parent);

            if (rb_is_red(sibling)) {
                rb_set_color(RB_BLACK, sibling);
                rb_set_color(RB_RED, parent);
                rb_rotate_right(parent, tree);
                sibling = rbtree_get_left(parent);
            }
            if ((!rbtree_get_left(sibling)  || rb_is_black(rbtree_get_left(sibling))) &&
                (!rbtree_get_right(sibling) || rb_is_black(rbtree_get_right(sibling)))) {
                rb_set_color(RB_RED, sibling);
                node = parent;
                parent = rb_get_parent(parent);
                continue;
            }
            if (!rbtree_get_left(sibling) || rb_is_black(rbtree_get_left(sibling))) {
                rb_set_color(RB_BLACK, rbtree_get_right(sibling));
                rb_set_color(RB_RED, sibling);
                rb_rotate_left(sibling, tree);
                sibling = rbtree_get_left(parent);
            }
            rb_set_color(rb_get_color(parent), sibling);
            rb_set_color(RB_BLACK, parent);
            rb_set_color(RB_BLACK, rbtree_get_left(sibling));
            rb_rotate_right(parent, tree);
            node = *tree;
            break;
        }
    } while (rb_is_black(node));

    if (node)
        rb_set_color(RB_BLACK, node);
}
Пример #5
0
static char *rbtree_insert(char *node, char **tree)
{
    char *key, *parent;
    int is_left;

    key = rb_do_lookup(node, *tree, &parent, &is_left);
    if (key)
        return key;

    rb_set_left(NULL, node);
    rb_set_right(NULL, node);
    rb_set_color(RB_RED, node);
    rb_set_parent(parent, node);

    if (parent) {
        rb_set_child(node, parent, is_left);
    } else {
        *tree = node;
    }

    /*
     * Fixup the modified tree by recoloring nodes and performing
     * rotations (2 at most) hence the red-black tree properties are
     * preserved.
     */
    while ((parent = rb_get_parent(node)) && rb_is_red(parent)) {
        char *grandpa = rb_get_parent(parent);

        if (parent == rbtree_get_left(grandpa)) {
            char *uncle = rbtree_get_right(grandpa);

            if (uncle && rb_is_red(uncle)) {
                rb_set_color(RB_BLACK, parent);
                rb_set_color(RB_BLACK, uncle);
                rb_set_color(RB_RED, grandpa);
                node = grandpa;
            } else {
                if (node == rbtree_get_right(parent)) {
                    rb_rotate_left(parent, tree);
                    node = parent;
                    parent = rb_get_parent(node);
                }
                rb_set_color(RB_BLACK, parent);
                rb_set_color(RB_RED, grandpa);
                rb_rotate_right(grandpa, tree);
            }
        } else {
            char *uncle = rbtree_get_left(grandpa);

            if (uncle && rb_is_red(uncle)) {
                rb_set_color(RB_BLACK, parent);
                rb_set_color(RB_BLACK, uncle);
                rb_set_color(RB_RED, grandpa);
                node = grandpa;
            } else {
                if (node == rbtree_get_left(parent)) {
                    rb_rotate_right(parent, tree);
                    node = parent;
                    parent = rb_get_parent(node);
                }
                rb_set_color(RB_BLACK, parent);
                rb_set_color(RB_RED, grandpa);
                rb_rotate_left(grandpa, tree);
            }
        }
    }
    rb_set_color(RB_BLACK, *tree);
    return NULL;
}
Пример #6
0
static inline void rb_delete_rebalance(struct rb_node* node,
                                       struct rb_node* parent,
                                       struct rb_root* root)
{
    struct rb_node* sibling;

    while ((!node || rb_is_black(node)) && (node != root->node)) {
        if (node == parent->left) {
            sibling = parent->right;

            if (rb_is_red(sibling)) {
                rb_rotate_left(parent, root);
                rb_set_red(parent);
                rb_set_black(sibling);
                sibling = parent->right;
            }

            if ((!sibling->left || rb_is_black(sibling->left)) &&
                (!sibling->right || rb_is_black(sibling->right))) {
                rb_set_red(sibling);
                node = parent;
                /* if (node) */ parent = rb_parent(node);
            } else {
                if (!sibling->right || rb_is_black(sibling->right)) {
                    rb_set_black(sibling->left);
                    rb_set_red(sibling);
                    rb_rotate_right(sibling, root);
                    sibling = parent->right;
                }

                rb_set_color(sibling, rb_color(parent));
                rb_set_black(parent);
                rb_set_black(sibling->right);
                rb_rotate_left(parent, root);
                node = root->node;

                break;
            }
        } else {
            sibling = parent->left;

            if (rb_is_red(sibling)) {
                rb_rotate_right(parent, root);
                rb_set_red(parent);
                rb_set_black(sibling);
                sibling = parent->left;
            }

            if ((!sibling->left || rb_is_black(sibling->left)) &&
                (!sibling->right || rb_is_black(sibling->right))) {
                rb_set_red(sibling);
                node = parent;
                /* if (node) */ parent = rb_parent(node);
            } else {
                if (!sibling->left || rb_is_black(sibling->left)) {
                    rb_set_black(sibling->right);
                    rb_set_red(sibling);
                    rb_rotate_left(sibling, root);
                    sibling = parent->left;
                }

                rb_set_color(sibling, rb_color(parent));
                rb_set_black(parent);
                rb_set_black(sibling->left);
                rb_rotate_right(parent, root);
                node = root->node;

                break;
            }
        }
    }

    if (node)
        rb_set_black(node);
}
Пример #7
0
void rb_arreglar_eliminacion(rb_arbol* arbol, rb_nodo* punta, rb_nodo* hermano) {
    rb_nodo* sobrino;
    rb_nodo* sobrino_nieto;
    

    if(rb_izquierdo(punta) == hermano) {
        if(rb_color(punta) == ROJO) {
            /*
                Caso c.1.1:
                Mi padre es rojo. Entonces, mi 
                hermano es negro.
            */ 
            
            /* Mi hermano tiene un hijo rojo? */
            if((rb_izquierdo(hermano) != arbol->nil && rb_color(rb_izquierdo(hermano)) == ROJO)) {
            
                /*
                El arbol tiene esta pinta:
                                P
                              /  \
                            H     z
                          /  \
                        C     y
                      /  \
                    w    x
                P = padre, H = hermano, C es rojo.
                z es donde yo estaba, que pasa de tener
                altura negra h a h-1.
                w, x e y todos tienen altura negra h-1.
                    
                */
                rb_rotar_derecha(arbol, punta);
                
                /*
                El arbol ahora tiene esta pinta:
                            H
                          /  \ 
                        C     P
                      /  \   / \
                    w     x y   z
                
                Es posible que y fuera rojo, entonces tengo
                que cambiarle el color a P. Pero hacer eso
                cambia la altura negra de z e y. Entonces
                pinto también a C de negro. Pero ahora w, x,
                y, z tienen altura h+1, y necesito que sea h.
                Entonces, pinto a H de rojo (no violo nada
                porque si el padre de H es rojo, entonces el
                padre de P antes era rojo, absurdo porque P
                era rojo).
                */
                rb_set_color(punta, NEGRO);
                rb_set_color(hermano, ROJO);
                rb_set_color(rb_izquierdo(hermano), NEGRO);
                
                /*
                    Ahora w, x, y, z tienen altura h. Terminé.
                */
            } else if((rb_derecho(hermano) != arbol->nil && rb_color(rb_derecho(hermano)) == ROJO)) {
                /* El hijo derecho de mi hermano es rojo.
                Entonces, el arbol tiene esta pinta:
                               P
                             /  \
                            H    z
                          /  \
                         w    C
                             | \
                            x   y
                Donde P es punta, H es hermano, C es rojo.
                Yo solía ser z.
                
                Quiero llevarlo a algo de la forma...   
                
                                C
                              /  \ 
                            H     P
                          /  \   / \
                        w     x y   z                 
                */
                
                               
                rb_rotar_izquierda(arbol, hermano); 
                
                /* El arbol ahora se ve así:
                                    P
                                  /  \
                                C     z
                              /  \
                            H     y
                          /  \
                        w    x 
                  
                  El izquierdo de la punta es lo que antes era
                  el derecho del hermano.
                */
                rb_rotar_derecha(arbol, punta);
                
                /* Ahora se vé así:
                                C
                              /  \ 
                            H     P
                          /  \   / \
                        w     x y   z                     
                
                
                Que es alo que queríamos llegar. Pero P y H
                tenían colores distintos. Entonces recoloreo
                para que todos los subarboles tengan altura h.
                */
                
                rb_set_color(punta, NEGRO);
                rb_set_color(hermano, NEGRO);
                rb_set_color(rb_padre(hermano), ROJO);
            } else {
                /* Caso c.1.2:
                Mi hermano no tiene un hijo rojo, y mi padre es rojo.
                Entonces, es fácil. El problema tiene esta pinta:
                            P
                          /  \
                         H    z
                       /  \    
                     x     y
                     
                 Donde x e y son negros, H es negro, P es rojo.
                 Pero entonces, simplemente recoloreamos P y H.
                 z gana una altura, x e y permanecen iguales.
             
                */
             
                rb_set_color(punta, NEGRO);
                rb_set_color(hermano, ROJO);
            }
        } else {
        
            /*  Caso c.2:
                Mi padre es negro.
            */
            
            /* Mi hermano es rojo? */
            if(rb_color(hermano) == ROJO) {
                /*  Caso c.2.1:
                    Mi hermano es rojo.
                */
                
                /* Mi sobrino es negro. */
                sobrino = rb_derecho(hermano);
                /* Tengo un sobrino-nieto (hijo de mi sobrino) rojo? */ 

                if(rb_izquierdo(sobrino) != arbol->nil && rb_color(rb_izquierdo(sobrino)) == ROJO) {
                    /*  Caso c.2.1.1: Tengo un sobrino-nieto rojo. 
                        El arbol tiene esta pinta:
                                    P
                                  /  \
                                H     z
                              /  \
                            v     S
                                 / \
                               SN   y
                              /  \  
                             w    x
                        z es donde yo solía estar.
                        Colores:
                            P  : Negro
                            H  : Rojo
                            S  : Negro
                            SN : Rojo
                            
                        Alturas negras de sub-arboles: 
                        
                            v : h
                            w : h-1
                            x : h-1
                            y : h-1
                            z : h -> h-1
                        
                        Para arreglar esto, hago dos rotaciones:
                    */
                    sobrino_nieto = rb_izquierdo(sobrino);
                    
                    rb_rotar_izquierda(arbol, hermano);
                    
                    /*
                        Ahora el arbol tiene esta pinta:
                                    P
                                  /  \
                                S     z
                              /  \
                            H     y
                           / \
                          v  SN
                            /  \
                           w    x
                           
                        Una rotación más y estamos...
                    
                    */
                    
                    rb_rotar_derecha(arbol, punta);
                    
                    /*
                        Ahora se vé así:
                                  S
                                /  \
                              H     P
                            / \    / \
                          v    \  y   z
                               SN
                              /  \
                             w    x
                        Y yá está balanceado.
                        Pero w y x tienen muy poca altura.
                        Entonces convertimos SN a negro.
                    */
                    
                    rb_set_color(sobrino_nieto, NEGRO);
                
                } else if(rb_derecho(sobrino) != arbol->nil && rb_color(rb_derecho(sobrino)) == ROJO) {
                    /* Caso c.2.1.1: Tengo un sobrino-nieto rojo. */
            
                   sobrino_nieto = rb_derecho(sobrino);

                    /* Parecido, solo que tengo que mover mas cosas: */
                    
                    /*  El arbol ahora tiene esta pinta:
                    
                                P
                              /  \
                            H     z
                          /  \
                         v    S
                            /  \
                           w   SN
                              /  \
                            x     y
                    
                    
                    Puedo rotar un par de veces...
                    */
                    
                    rb_rotar_izquierda(arbol, sobrino);
                    /*
                        Ahora tenemos esto:
                        
                                P
                              /  \
                            H     z
                           / \
                          v  SN
                             / \
                            S   y
                           / \ 
                          w  x
        
                        Igual que en el caso anterior, rotamos y recoloreamos.
                    */
                    rb_rotar_derecha(arbol, punta);
                    rb_rotar_derecha(arbol, punta);
                    rb_set_color(hermano, NEGRO);
                    
                } else {
                    /* No tengo un sobrino-nieto rojo. */
                    
                    /* El arbol se parece a esto:
                                P
                              /  \
                            H     z
                          /  \
                         w    S
                             / \
                            x   y
                            
                        Donde x e y tienen puntas negras.
                        
                        Podemos rotar y colorear 1 vez, y funca.
                    */
                    
                    rb_rotar_derecha(arbol, punta);
                    rb_set_color(hermano, NEGRO);
                    rb_set_color(sobrino, ROJO);  /* está bien, porque sus dos hijos eran negros */
                }
                
                
            } else {
                /* Mi hermano no es rojo. */
                
                /* Tengo un sobrino rojo? */
                if(rb_derecho(hermano) != arbol->nil && rb_color(rb_derecho(hermano)) == ROJO) {
                    sobrino = rb_derecho(hermano);
                    rb_rotar_izquierda(arbol, hermano);
                    rb_rotar_derecha(arbol, punta);
                    rb_set_color(sobrino, NEGRO);
                } else if(rb_izquierdo(hermano) != arbol->nil && rb_color(rb_izquierdo(hermano)) == ROJO) {
                    sobrino = rb_izquierdo(hermano);
                    rb_rotar_derecha(arbol, punta);
                    rb_set_color(sobrino, NEGRO);
                } else {
                    /*  Solo tengo que recolorear a mi hermano
                        de rojo. Pero este sub-arbol acaba de cagarla.
                        Entonces, vuelvo a empezar este procedimiento.
                    */

                    rb_set_color(hermano, ROJO);
                    if(punta == rb_arbol_raiz(arbol)) {
                        rb_set_color(punta, NEGRO);
                        return;
                    }
                    rb_arreglar_eliminacion(arbol, rb_padre(punta), rb_hermano(punta));
                }
            
            }
        
        }
    } else {
        /* Casos simétricos */
        if(rb_color(punta) == ROJO) {
            if((rb_derecho(hermano) != arbol->nil && rb_color(rb_derecho(hermano)) == ROJO)) {
                rb_rotar_izquierda(arbol, punta);
                rb_set_color(punta, NEGRO);
                rb_set_color(hermano, ROJO);
                rb_set_color(rb_derecho(hermano), NEGRO);
            } else if((rb_izquierdo(hermano) != arbol->nil && rb_color(rb_izquierdo(hermano)) == ROJO)) {
                rb_rotar_derecha(arbol, hermano);
                rb_rotar_izquierda(arbol, punta);
                rb_set_color(punta, NEGRO);
                rb_set_color(hermano, NEGRO);
                rb_set_color(rb_padre(hermano), ROJO);
            } else {                
                rb_set_color(punta, NEGRO);
                rb_set_color(hermano, ROJO);
            }
        } else {  
            if(rb_color(hermano) == ROJO) {
                sobrino = rb_izquierdo(hermano);
                if(rb_derecho(sobrino) != arbol->nil && rb_color(rb_derecho(sobrino)) == ROJO) {
                    sobrino_nieto = rb_derecho(sobrino);
                    rb_rotar_derecha(arbol, hermano);
                    rb_rotar_izquierda(arbol, punta);
                    rb_set_color(sobrino_nieto, NEGRO);                    
                } else if(rb_izquierdo(sobrino) != arbol->nil && rb_color(rb_izquierdo(sobrino)) == ROJO) {
                    sobrino_nieto = rb_izquierdo(sobrino);
                    rb_rotar_derecha(arbol, sobrino);
                    rb_rotar_izquierda(arbol, punta);
                    rb_rotar_izquierda(arbol, punta);
                    rb_set_color(hermano, NEGRO);
                } else {
                    rb_rotar_izquierda(arbol, punta);
                    rb_set_color(hermano, NEGRO);
                    rb_set_color(sobrino, ROJO);
                }              
            } else {
                if(rb_izquierdo(hermano) != arbol->nil && rb_color(rb_izquierdo(hermano)) == ROJO) {
                    sobrino = rb_izquierdo(hermano);
                    rb_rotar_derecha(arbol, hermano);
                    rb_rotar_izquierda(arbol, punta);
                    rb_set_color(sobrino, NEGRO);
                } else if(rb_derecho(hermano) != arbol->nil && rb_color(rb_derecho(hermano)) == ROJO) {
                    sobrino = rb_derecho(hermano);
                    rb_rotar_izquierda(arbol, punta);
                    rb_set_color(sobrino, NEGRO);
                } else {
                    rb_set_color(hermano, ROJO);
                    if(punta == rb_arbol_raiz(arbol)) {
                        rb_set_color(punta, NEGRO);
                        return;
                    }
                    rb_arreglar_eliminacion(arbol, rb_padre(punta), rb_hermano(punta));
                }
            }
        }
    }
}
Пример #8
0
/*
 * 红黑树删除修正函数
 *
 * 在从红黑树中删除插入节点之后(红黑树失去平衡),再调用该函数;
 * 目的是将它重新塑造成一颗红黑树。
 *
 * 参数说明:
 *     root 红黑树的根
 *     node 待修正的节点
 */
static void rbtree_delete_fixup(RBRoot *root, Node *node, Node *parent)
{
    Node *other;

    while ((!node || rb_is_black(node)) && node != root->node)
    {
        if (parent->left == node)
        {
            //1.         parent                     parent.r                     old.ohter.b         
            //           /     \                   /        \                    /         \
            //       child.b    other.r         child.b    other.b           parent.r       d
            //        /   \    /      \         /     \    /     \           /       \
            //       a     b  c        d       a     b     c      d       child.b     c  <- new.other
            //                                                            /     \
            //                                                           a       b
            other = parent->right;                    
            if (rb_is_red(other))
            {
                // Case 1: x的兄弟w是红色的  
                rb_set_black(other);
                rb_set_red(parent);
                rbtree_left_rotate(root, parent);
                other = parent->right;
            }
			//2.       gparent                     gparent         3. <- new.parent
			//           |
			//         parent                      parent          2. <- new.child
			//        /      \                    /      \
			//   child.b     other         old.child.b    other.r  1. <- color = RED
			//   /     \     /    \
			//  a      b    c.b  d.b    

            if ((!other->left || rb_is_black(other->left)) &&
                (!other->right || rb_is_black(other->right)))
            {
                // Case 2: x的兄弟w是黑色,且w的俩个孩子也都是黑色的  
                rb_set_red(other);
                node = parent;
                parent = rb_parent(node);
            }
            else
            {   
                if (!other->right || rb_is_black(other->right))
                {
			//3.1         parent                  parent                                            parent
			//           /      \                /      \                                          /        \
			//     child.b     other.b     child.b      other.r      <- color RED           child.b        c.b                 <- new.other
			//     /    \      /     \      /  \         /    \                              /   \            \
			//    a      b    c      d.b   a   b       c.b     d.b   <- c.color BLACK        a    b           old.other.r
			//                                                                                                /        \
			//                                                                                                         d.b
                    // Case 3: x的兄弟w是黑色的,并且w的左孩子是红色,右孩子为黑色。  
                    rb_set_black(other->left);
                    rb_set_red(other);
                    rbtree_right_rotate(root, other);
                    other = parent->right;
                }
			//3.2       parent.c                parent.b          2<- color BLACK                       other.b
			//         /      \                /        \                                             /       \
			//    child.b    other.b         child.b    other.c   1<- color parent.color         parent.b      d.b
			//    /    \     /      \        /     \    /     \                                 /     \
			//   a     b    c       d.r    a      b     c     d.b 3<- color BLACK            child.b    c
			//                                                                              /     \
			//                                                                             a       b
                // Case 4: x的兄弟w是黑色的;并且w的右孩子是红色的,左孩子任意颜色。
                rb_set_color(other, rb_color(parent));
                rb_set_black(parent);
                rb_set_black(other->right);
                rbtree_left_rotate(root, parent);
                node = root->node;
                break;
            }
        }
        else
        {
            other = parent->left;
            if (rb_is_red(other))
            {
                // Case 1: x的兄弟w是红色的  
                rb_set_black(other);
                rb_set_red(parent);
                rbtree_right_rotate(root, parent);
                other = parent->left;
            }
            if ((!other->left || rb_is_black(other->left)) &&
                (!other->right || rb_is_black(other->right)))
            {
                // Case 2: x的兄弟w是黑色,且w的俩个孩子也都是黑色的  
                rb_set_red(other);
                node = parent;
                parent = rb_parent(node);
            }
            else
            {
                if (!other->left || rb_is_black(other->left))
                {
                    // Case 3: x的兄弟w是黑色的,并且w的左孩子是红色,右孩子为黑色。  
                    rb_set_black(other->right);
                    rb_set_red(other);
                    rbtree_left_rotate(root, other);
                    other = parent->left;
                }
                // Case 4: x的兄弟w是黑色的;并且w的右孩子是红色的,左孩子任意颜色。
                rb_set_color(other, rb_color(parent));
                rb_set_black(parent);
                rb_set_black(other->left);
                rbtree_right_rotate(root, parent);
                node = root->node;
                break;
            }
        }
    }
    if (node)
        rb_set_black(node);
}