/*保持红黑树的性质
 * 红黑树的那些性质可能被破坏?
 * 性质2:根节点是黑的,如果插入的结点是根节点,即未插入前红黑树是空树,
 * 则性质2被破坏
 * 性质4:如果一个结点是红色,则其子女都是黑的。如果插入结点后,该结点
 * 的父亲结点也是红色,则破坏了性质4.
 */
prbtree rbt_insert_fixup(prbtree T, prbtree z)
{
  prbtree y;
  while(z->parent->color == RED)
    {
      assert(z->parent != nil);
      // 如果z的父节点是其祖父结点的左子女
      assert(z->parent->parent != nil);
      if (z->parent == z->parent->parent->left)
	{
	  //y 记录其叔父结点
	  y = z->parent->parent->right;
	  // 不击穿 如果y所指向的结点的颜色是红色,case 1
	  if (y->color == RED)
	    {
	      // 更新z的同时更新y结点
	      // 将z->parent 和 y 染成黑色
	      // z->parent->parent染成红色
	      // z结点上升两层,指向其祖父,
	      // 要更新y结点吗? 让其自动进入下一循环
	      z->parent->color = BLACK;
	      y->color = BLACK;
	      z->parent->parent->color = RED;
	      z = z->parent->parent;
	      // 更新了z结点后	      
	    }
	  // 如果y所指向的结点的颜色是黑色,case 2 or case3
	  else 
	    {
	      // 击穿 如果z所指向的结点是其父节点的右儿子 case 2
	      // 以z的父节点为轴,立即来一次左旋,将其转换为case 3
	      if (z == z->parent->right)
		{
		  // 旋转后重新获得根节点的指针
		  z = z->parent;
		  T = rbt_left_rotate(T,z);
		}
	      // 如果z所指向的结点是其父节点的左儿子 case 3
	      // 改变z->parent的颜色为黑色,z->parent->parent颜色为红色,以其祖父节点为轴,右旋,循环结束
	      if (z == z->parent->left)
		{
		  z->parent->color = BLACK;
		  z->parent->parent->color = RED;
		  T = rbt_right_rotate(T, z->parent->parent);
		}
	    }
	}
      // 如果z的父节点是其祖父结点的右子女
      else // z->parent == z->parent->parent->right
	{
	  // 交换左右子女,进行处理
	  // 记录其叔父结点
	  y = z->parent->parent->left;
	  // 如果y是红色 case 1
	  if (y->color == RED)
	    {
	      z->parent->color = BLACK;
	      y->color = BLACK;
	      z->parent->parent->color = RED;
	      z = z->parent->parent;
	    }
	  else // 如果y是黑色 case 2 或者 case 3
	    {
	      // 如果z是其父亲的左孩子,将其转换为右孩子 case 2
	      if (z == z->parent->left)
		{
		  z = z->parent;
		  T = rbt_right_rotate(T, z);
		}
	      // 现在z是其父亲的右孩子了,case 3
	      // 将其父亲染为黑色,其祖父染为红色,左旋
	      z->parent->color = BLACK;
	      z->parent->parent->color = RED;
	      T = rbt_left_rotate(T, z->parent->parent);
	    }
	}
    }
  T->color = BLACK;
  return T;
}
Exemple #2
0
/******************************************************************************
 **函数名称: rbt_delete_fixup
 **功    能: 修复删除操作造成的黑红树性质的破坏(内部接口)
 **输入参数: 
 **     tree: 红黑树
 **     node: 实际被删结点的替代结点(注: node有可能是叶子结点)
 **输出参数: NONE
 **返    回: RBT_OK:成功  RBT_ERR:失败
 **实现描述: 
 **注意事项: 被删结点为黑色结点,才能调用此函数进行性质调整
 **作    者: # Qifeng.zou # 2013.12.28 #
 ******************************************************************************/
static int rbt_delete_fixup(rbt_tree_t *tree, rbt_node_t *node)
{
    rbt_node_t *parent = NULL, *brother = NULL;

    while (rbt_is_black(node) && (tree->root != node)) {   
        /* Set parent and brother */
        parent = node->parent;
        
        if (node == parent->lchild) {
            brother = parent->rchild;

            /* Case 1: 兄弟结点为红色:  以parent为支点, 左旋处理 */
            if (rbt_is_red(brother)) {
                rbt_set_red(parent);
                rbt_set_black(brother);
                rbt_left_rotate(tree, parent);

                /* 参照结点node不变, 兄弟结点改为parent->rchild */
                brother = parent->rchild;
                
                /* 注意: 此时处理还没有结束,还需要做后续的调整处理 */
            }

            /* Case 2: 兄弟结点为黑色(默认), 且兄弟结点的2个子结点都为黑色 */
            if (rbt_is_black(brother->lchild) && rbt_is_black(brother->rchild)) {
                rbt_set_red(brother);
                node = parent;
            }
            else {
                /* Case 3: 兄弟结点为黑色(默认),
                    兄弟节点的左子结点为红色, 右子结点为黑色:  以brother为支点, 右旋处理 */
                if (rbt_is_black(brother->rchild)) {
                    rbt_set_black(brother->lchild);
                    rbt_set_red(brother);

                    rbt_right_rotate(tree, brother);

                    /* 参照结点node不变 */
                    brother = parent->rchild;
                }
                
                /* Case 4: 兄弟结点为黑色(默认),
                    兄弟结点右孩子结点为红色:  以parent为支点, 左旋处理 */
                rbt_copy_color(brother, parent);
                rbt_set_black(brother->rchild);
                rbt_set_black(parent);

                rbt_left_rotate(tree, parent);
                
                node = tree->root;
            }
        }
        else
        {
            brother = parent->lchild;

            /* Case 5: 兄弟结点为红色:  以parent为支点, 右旋处理 */
            if (rbt_is_red(brother)) {
                rbt_set_red(parent);
                rbt_set_black(brother);

                rbt_right_rotate(tree, parent);

                /* 参照结点node不变 */
                brother = parent->lchild;
                
                /* 注意: 此时处理还没有结束,还需要做后续的调整处理 */
            }

            /* Case 6: 兄弟结点为黑色(默认), 且兄弟结点的2个子结点都为黑色 */
            if (rbt_is_black(brother->lchild) && rbt_is_black(brother->rchild)) {
                rbt_set_red(brother);
                node = parent;
            }
            else {
                /* Case 7: 兄弟结点为黑色(默认),
                    兄弟节点的右子结点为红色, 左子结点为黑色:  以brother为支点, 左旋处理 */
                if (rbt_is_black(brother->lchild)) {
                    rbt_set_red(brother);
                    rbt_set_black(brother->rchild);

                    rbt_left_rotate(tree, brother);

                    /* 参照结点node不变 */
                    brother = parent->lchild;
                }
            
                /* Case 8: 兄弟结点为黑色(默认),
                    兄弟结点左孩子结点为红色: 以parent为支点, 右旋处理 */
                rbt_copy_color(brother, parent);
                rbt_set_black(brother->lchild);
                rbt_set_black(parent);

                rbt_right_rotate(tree, parent);
                
                node = tree->root;
            }
        }
    }

    rbt_set_black(node);
    
    rbt_assert(tree, node);
    rbt_assert(tree, brother);
    rbt_assert(tree, parent);
    return RBT_OK;
}
/**
 * 删除结点后保持红黑树性质的函数
 */
prbt_node rbt_delete_fixup(prbtree T, prbt_node x)
{
     prbt_node w;
     // 当x!=T且x的颜色为黑时循环继续
     while(x != T && x->color == BLACK)
     {
	  // 如果x是其父结点左孩子
	  if (x == x->parent->left)
	  {
	       w = x->parent->right;
	       // 击穿 case 1
	       // 如果w的颜色是红色,则x->parent的颜色必定为黑色
	       // w必定不是叶结点
	       if (w->color == RED)
	       {
		    // 交换w和x->parent的颜色
		    // 对x->parent进行一次左旋
		    // 使case 1 转变成case 2、3、4
		    w->color = BLACK;
		    x->parent->color = RED;
		    T = rbt_left_rotate(T, x->parent);
		    w = x->parent->right;
	       }
	       // case 2
	       // 此时w必定是黑色
	       // 如果w的左右孩子都是黑色
	       // 改变颜色,循环结束或x指针上升一层
	       if (w->left->color == BLACK && w->right->color == BLACK)
	       {
		    w->color = RED;
		    x = x->parent;
	       }
	       else 
	       {
		    // 如果w的右孩子是黑色,则w的左孩子是红色
		    // case 3
		    // 交换w和其左孩子的颜色,对w进行一次右旋
		    // 最终使w的右孩子是红色,转换成case 4
		    if (w->right->color == BLACK)
		    {
			 w->color = RED;
			 w->left->color = BLACK;
			 T = rbt_right_rotate(T, w);
			 w = x->parent->right;
		    }
		    // case 4
		    // w的右孩子是红色,w的左孩子的颜色未知
		    // 交换x->parent 和 w的颜色,
		    // 将w的右孩子赋值为黑色,对x->parent进行一次左旋
		    w->color = x->parent->color;
		    x->parent->color = BLACK;
		    w->right->color = BLACK;
		    T = rbt_left_rotate(T, x->parent);
		    x = T;		    
	       }
	  }
	  // 如果x是x->parent的右孩子,对称处理
	  else
	  {
	       w = x->parent->left;
	       // case 1
	       if (w->color == RED)
	       {
		    w->color = BLACK;
		    x->parent->color = RED;
		    T = rbt_right_rotate(T, x->parent);
		    w = x->parent->left;
	       }
	       // case 2
	       if (w->right->color == BLACK && w->left->color == BLACK)
	       {
		    w->color = RED;
		    x = x->parent;
	       }
	       else
	       {
		    // case 3
		    if (w->left->color == BLACK)
		    {
			 w->color = RED;
			 w->right->color = BLACK;
			 T = rbt_left_rotate(T, w);
			 w = x->parent->left;
		    }
		    // case 4
		    w->color = x->parent->color;
		    x->parent->color = BLACK;
		    w->left->color = BLACK;
		    T = rbt_right_rotate(T, x->parent);
		    x = T;		    
	       }
	  }
     }
     x->color = BLACK;
     return T;
}
Exemple #4
0
/******************************************************************************
 **函数名称: rbt_insert_fixup
 **功    能: 插入操作修复(内部接口)
 **输入参数: 
 **     tree: 红黑树
 **     node: 新增节点的地址
 **输出参数: NONE
 **返    回: RBT_OK:成功 RBT_ERR:失败
 **实现描述: 
 **     1. 检查红黑树性质是否被破坏
 **     2. 如果被破坏,则进行对应的处理
 **注意事项: 插入节点操作只可能破坏性质④
 **作    者: # Qifeng.zou # 2013.12.23 #
 ******************************************************************************/
static int rbt_insert_fixup(rbt_tree_t *tree, rbt_node_t *node)
{
    rbt_node_t *parent = NULL, *uncle = NULL, *grandpa = NULL, *gparent = NULL;

    while (rbt_is_red(node)) {
        parent = node->parent;
        if (rbt_is_black(parent)) {
            return RBT_OK;
        }
        
        grandpa = parent->parent;
        if (parent == grandpa->lchild) { /* 父节点为左节点 */
            uncle = grandpa->rchild;
            /* case 1: 父节点和叔节点为红色 */
            if (rbt_is_red(uncle)) {
                rbt_set_black(parent);
                rbt_set_black(uncle);
                if (grandpa != tree->root) {
                    rbt_set_red(grandpa);
                }
                node = grandpa;
                continue;
            }
            /* case 2: 叔结点为黑色,结点为左孩子 */
            else if (node == parent->lchild) {
                /* 右旋转: 以grandpa为支点 */
                gparent = grandpa->parent;
                rbt_set_red(grandpa);
                rbt_set_black(parent);

                rbt_right_rotate(tree, grandpa);
                node = gparent;
                continue;
            }
            /* case 3: 叔结点为黑色,结点为右孩子 */
            else
            {
                /* 左旋转: 以parent为支点 */
                rbt_left_rotate(tree, parent);
                
                node = parent;
                continue;
            }
        }
        else                        /* 父节点为右孩子 */
        {
            uncle = grandpa->lchild;
            
            /* case 1: 父节点和叔节点为红色 */
            if (rbt_is_red(uncle)) {
                rbt_set_black(parent);
                rbt_set_black(uncle);
                if (grandpa != tree->root) {
                    rbt_set_red(grandpa);
                }

                node = grandpa;
                continue;
            }
            /* case 2: 叔结点为黑色,结点为左孩子 */
            else if (node == parent->lchild) {
                /* 右旋转: 以parent为支点 */
                rbt_right_rotate(tree, parent);
                node = parent;
                continue;
            }
            /* case 3: 叔结点为黑色,结点为右孩子 */
            else {
                /* 左旋转: 以grandpa为支点 */
                gparent = grandpa->parent;
                rbt_set_black(parent);
                rbt_set_red(grandpa);

                rbt_left_rotate(tree, grandpa);
                node = gparent;
                continue;
            }
        }
    }

    return RBT_OK;
}