/*保持红黑树的性质 * 红黑树的那些性质可能被破坏? * 性质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; }
/****************************************************************************** **函数名称: 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; }
/****************************************************************************** **函数名称: 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; }