花了好几天的业余时间,看文章,总算是用C实现了一遍红黑树,主要还是自己C语言水平不够高,调试断点浪费了不少时间,闲话少说
·····································LSP的分割线·····································
最近整理代码,在掘金整理了最新的红黑树实现代码,比这里更整洁,这里就不重新发了,详见同名掘金博客
1. 红黑树结构体//这里偷懒就应0代表黑色,1代表红色了
typedef struct RBTreeNode {
int data; //数据域
int color; //0黑色 1红色
struct RBTreeNode *parent;//父亲结点
struct RBTreeNode *left; //左子结点
struct RBTreeNode *right; //右子结点
} RBTreeNode;
2. 前序遍历//这里打印了节点的颜色和父节点
void preOrderTraverse(RBTreeNode *root)
{
if (root != NULL)
{
if (root->parent != NULL)
{
printf("%d color: %d parent:%d\n", root->data, root->color, root->parent->data);
}else{
printf("%d color: %d\n", root->data, root->color);
}
preOrderTraverse(root->left);
preOrderTraverse(root->right);
}
}
3.1 左旋
跟AVL树差不多,多了parent相关的操作/**
* 左旋
* parent parent
* 8 12
* 4 12 8 50
* 9 50 => 4 9 70
* 70
*/
RBTreeNode *left_rotation(RBTreeNode *root)
{
struct RBTreeNode *new_root;
new_root = root->right;
root->right = new_root->left;
//将9的父亲设置为老的root 即8
if (new_root->left != NULL)
{
new_root->left->parent = root;
}
//新root的parent即老parent
new_root->parent = root->parent;
//然后处理老root的parent
if (root->parent == NULL)
{
//老root是根节点
new_root->parent = NULL;
}else{
//判断父亲左右
if (new_root->parent->left == root)
{
new_root->parent->left = new_root;
}else{
new_root->parent->right = new_root;
}
}
root->parent = new_root;
new_root->left = root;
return new_root;
}
3.2 右旋/**
* 右旋
* 8 4
* 4 12 2 8
* 2 6 => 1 6 12
* 1
*/
RBTreeNode *right_rotation(RBTreeNode *root)
{
struct RBTreeNode *new_root;
new_root = root->left;
root->left = new_root->right;
//将6的父亲设置为老的root 即8
if (new_root->right != NULL)
{
new_root->right->parent = root;
}
//新root的parent即老parent
new_root->parent = root->parent;
//然后处理老root的parent
if (root->parent == NULL)
{
//老root是根节点
new_root->parent = NULL;
}else{
//判断父亲左右
if (new_root->parent->left == root)
{
new_root->parent->left = new_root;
}else{
new_root->parent->right = new_root;
}
}
new_root->right = root;
root->parent = new_root;
// printf("***自己right_rotation***: \n");
// printfNode(new_root);
// printf("***左***: \n");
// printfNode(new_root->left);
// printf("***右***: \n");
// printfNode(new_root->right);
return new_root;
}
3.3 代码图解/**
* 1.插入的只有一个根节点
*
* 8(R) => 8(B)
*
* 2.1父节点是黑色,啥也不用干
* 8(B)
* / => 不变
* 4(R)
*
* 2.2 父节点是红色,祖父一定是黑色啦,看叔叔是啥颜色
*
* 2.2.1 父节点是祖父节点的左节点
*
* 2.2.1.1如果叔叔也是红色
* 将父节点,叔节点设为黑色,将祖父节点设为红色,将祖父节点设为“当前节点”(红色节点);即,之后递归继续对“当前节点”进行操作
*
* 8(B) 8(R) 8(B)
* / \ / \ / \
* 4(R) 12(R) => 4(B) 12(B) => 4(B) 12(B)
* / / /
* 2(R) 2(R) 2(R)
*
* 2.2.1.2如果叔叔不存在或是黑色
* 2.2.1.2.1新节点在左子树
* 父节点设为黑色,将祖父节点设为红色,对祖父节点右旋
*
* 8(B) 8(R) 8(B)
* / \ 着色 / \ 对4右旋 / \
* 4(B) 12(B) => 4(R) 12(B) => 2(B) 12(B)
* / / / \
* 2(R) 2(B) 1(R) 4(R)
* / /
* 1(R) 1(R)
*
* 2.2.1.2.2新节点在右子树
* root与父节点交换 并把父节点设为新root的左节点,即转化为2.2.1.2.1,处理如上
*
* 8(B) 8(B) 8(B) 8(B)
* / \ 交换 / \ 着色 / \ 对4右旋 / \
* 4(B) 12(B) => 4(B) 12(B) => 4(R) 12(B) => 3(B) 12(B)
* / / / / \
* 2(R) 3(R) 3(B) 2(R) 4(R)
* \ / /
* 3(R) 2(R) 2(R)
*
*
*
* 2.2.2 父节点是祖父节点的右节点
* 2.2.2.1如果叔叔也是红色
* 将父节点,叔节点设为黑色,将祖父节点设为红色,将祖父节点设为“当前节点”(红色节点);即,之后递归继续对“当前节点”进行操作
*
* 8(B) 8(R) 8(B)
* / \ / \ / \
* 4(R) 12(R) => 4(B) 12(B) => 4(B) 12(B)
* \ \ \
* 20(R) 20(R) 20(R)
*
* 2.2.2.2如果叔叔不存在或是黑色(这里的绘图简化些,其实都一样的)
* 2.2.2.2.1新节点在左子树
* root与父节点交换 并把父节点设为新root的右节点,即转化为2.2.2.2.2
* 8(B) 8(B) 8(R) 10(B)
* \ 交换 \ 着色 \ 对8右旋 / \
* 12(R) => 10(R) => 10(B) => 8(R) 12(R)
* / \ \
* 10(R) 12(R) 12(R)
*
* 2.2.2.2.2新节点在右子树
* 将父节点设为黑色 将祖父节点设为红色 左旋
*
* 8(B) 8(R) 12(B)
* \ 着色 \ 对8左旋 / \
* 12(B) => 12(B) => 8(R) 20(R)
* \ \
* 20(R) 20(R)
*
*
*/
4. 自平衡RBTreeNode *rebalance3(RBTreeNode *root, RBTreeNode *rootNode)//返回新的根节点
{
//1 插入根节点,只需置黑即可
if (root->parent == NULL)
{
root->color = 0;
}
//2 有父节点
if (root->parent != NULL)
{
//2.1 父节点是黑色,啥也不用干
if (root->parent->color == 0)
{
//do nothing
}else{
//2.2 父节点是红色,祖父一定是黑色啦,看叔叔是啥颜色
RBTreeNode *parent, *gparent, *uncle;
parent = root->parent;
gparent = root->parent->parent;
int return_flag = 0;
if (gparent == rootNode)
{
return_flag = 1;
}
//先判断父节点是祖父节点的左节点还是右节点,即叔叔节点是啥
//2.2.1 父节点是祖父节点的左节点
if (parent == gparent->left)
{
uncle = gparent->right;
//2.2.1.1如果叔叔也是红色
if (uncle != NULL && uncle->color == 1)
{
//1.将父节点设为黑色
parent->color = 0;
//2.将叔节点设为黑色
uncle->color = 0;
//3.将祖父节点设为红色
gparent->color = 1;
//4.将祖父节点设为“当前节点”(红色节点);即,之后继续对“当前节点”进行操作
return rebalance3(gparent, rootNode);
}else{
//2.2.1.2如果叔叔黑色 或不存在
//2.2.1.2.1 root是左节点
if (root == parent->left)
{
//1.将父节点设为黑色
parent->color = 0;
//2.将祖父节点设为红色
gparent->color = 1;
gparent = right_rotation(gparent);
}else{
//2.2.1.2.2 root是右节点
//1.root与父节点交换 并把父节点设为新root的左节点,即转化为2.2.1.2.1
gparent->left = root;
root->parent = gparent;
root->left = parent;
parent->parent = root;
parent->right = NULL;
return rebalance3(parent, rootNode);
}
}
}else{
//2.2.2 父节点是祖父节点的右节点
uncle = gparent->left;
//2.2.2.1如果叔叔也是红色
if (uncle != NULL && uncle->color == 1)
{
//1.将父节点设为黑色
parent->color = 0;
//2.将叔节点设为黑色
uncle->color = 0;
//3.将祖父节点设为红色
gparent->color = 1;
//4.将祖父节点设为“当前节点”(红色节点);即,之后继续对“当前节点”进行操作
return rebalance3(gparent, rootNode);
}else{
//2.2.2.2如果叔叔黑色 或不存在
//2.2.2.2.1 root是左节点
if (root == parent->left)
{
//1.root与父节点交换 并把父节点设为新root的左节点,即转化为2.2.2.2.2
gparent->right = root;
root->parent = gparent;
root->right = parent;
parent->parent = root;
parent->left = NULL;
return rebalance3(parent, rootNode);
}else{
//2.2.2.2.2 root是右节点
//1.将父节点设为黑色
parent->color = 0;
//2.将祖父节点设为红色
gparent->color = 1;
gparent = left_rotation(gparent);
}
}
}
if (return_flag == 1)
{
return gparent;
}
}
}
return rootNode;
}
5.1 插入(未平衡)RBTreeNode *getNode(int data, RBTreeNode *parent)
{
struct RBTreeNode *node;
node = (struct RBTreeNode *)malloc(sizeof(struct RBTreeNode));
if (node == NULL)
{
printf("malloc error \n");
return NULL;
}
node->data = data;
node->parent= parent;
node->color = 1;
node->right = NULL;
node->left = NULL;
if (parent == NULL)
{
node->color = 0;
}
RBTreeEndNode = node;
return node;
}
RBTreeNode *insert(RBTreeNode *root, int data, RBTreeNode *parent)
{
if (NULL == root)
{
return getNode(data, parent);
}
if (data >= root->data)
{
root->right = insert(root->right, data, root);
}else{
root->left = insert(root->left, data, root);
}
return root;
}
5.2 插入(平衡)RBTreeNode *inserRB(RBTreeNode *root, int data, RBTreeNode *parent)
{
root = insert(root,data,parent);
return rebalance3(RBTreeEndNode,root);
}
6 测试红黑树构建int main()
{
struct RBTreeNode *node;
//2.2.1.1 测试用例
node = NULL;
node = inserRB(node, 8, NULL);
node = inserRB(node, 4, NULL);
node = inserRB(node, 12, NULL);
node = inserRB(node, 2, NULL);
printf("***2.2.1.1 测试用例 前序***: \n");
preOrderTraverse(node);
//2.2.1.2.1 测试用例
node = NULL;
node = inserRB(node, 8, NULL);
node = inserRB(node, 4, NULL);
node = inserRB(node, 12, NULL);
node = inserRB(node, 2, NULL);
node = inserRB(node, 1, NULL);
printf("***2.2.1.2.1 测试用例 前序***: \n");
preOrderTraverse(node);
//2.2.1.2.2 测试用例
node = NULL;
node = inserRB(node, 8, NULL);
node = inserRB(node, 4, NULL);
node = inserRB(node, 12, NULL);
node = inserRB(node, 2, NULL);
node = inserRB(node, 3, NULL);
printf("***2.2.1.2.2 测试用例 前序***: \n");
preOrderTraverse(node);
//2.2.2.1 测试用例
node = NULL;
node = inserRB(node, 8, NULL);
node = inserRB(node, 4, NULL);
node = inserRB(node, 12, NULL);
node = inserRB(node, 20, NULL);
printf("***2.2.2.1 测试用例 前序***: \n");
preOrderTraverse(node);
//2.2.2.2.1 测试用例
node = NULL;
node = inserRB(node, 8, NULL);
node = inserRB(node, 12, NULL);
node = inserRB(node, 10, NULL);
printf("***2.2.2.2.1 测试用例 前序***: \n");
preOrderTraverse(node);
//2.2.2.2.2 测试用例
node = NULL;
node = inserRB(node, 8, NULL);
node = inserRB(node, 12, NULL);
node = inserRB(node, 20, NULL);
printf("***2.2.2.2.2 测试用例 前序***: \n");
preOrderTraverse(node);
}
测试结果:
7 红黑树删除图解*删除
*
*1.没有左右节点
*
* 1.1被删除节点是红色,直接删除即可
*
* 8(B) 8(B)
* / =>
* 4(R)
*
* 1.2被删除节点是黑色,破坏了平衡性 需要重新平衡
*
* 1.2.1被删除节点在父节点的左数上
*
* 1.2.1.1兄弟节点是黑色,
*
* 1.2.1.1.1 兄弟节点是黑色,且有一个右节点,右节点必然是红色
* parent parent parent
* | | |
* 8(可红可黑) 把父节点颜色赋值给14 8(可红可黑) 12(B)
* / \ 删除4 着色 \ 对8左旋 / \
* 4(B) 12(B) => 12(B) => 8(可红可黑) 14(可红可黑) 最终保持黑色节点数量依旧是1或者2个
* \ \
* 14(R)必然是红色 14(可红可黑,8是啥色 这里就啥色,下同)
*
* 1.2.1.1.2 兄弟节点是黑色,且有一个左节点,左节点必然是红色
* parent parent parent
* | 把父节点颜色赋值给兄弟节点 | |
* 8(可红可黑) 类似插入时候如右图 兄左置黑 8(可红可黑) 10(B)
* / \ 删除4 着色 转变为1.2.1.1 \ 对8左旋 / \
* 4(B) 12(B) => 10(B) => 8(可红可黑) 12(可红可黑) 最终保持黑色节点数量依旧是1或者2个
* / \
* 10(R)必然是红色 12(可红可黑)
*
* 1.2.1.1.3 兄弟节点是黑色,且有俩节点,必然都是红色
* parent parent parent
* | 把父节点颜色赋值给兄弟节点 | |
* 8(可红可黑) 把兄弟节点的右节点置黑 8(黑) 12(可红可黑)
* / \ 把父节点置黑 删除4 \ 对8左旋 / \
* 4(B) 12(B) => 12(可红可黑) => 8(B) 14(B) 最终保持黑色节点数量依旧是1或者2个
* / \ / \ \
* 10(R) 14(R)必然都是红色 10(R) 14(B) 10(R)
* 1.2.1.1.4 兄弟节点是黑色,且没有节点 黑色路径必然要-1了 递归
*
*
* (此处例外,不是删除4,而是删除10节点)
* parent parent parent
* | | |
* 8(可红可黑) 删除10(黑) 8(可红可黑) 8(可红可黑)
* / \ 把14置红 下一步rebalance / \ rebalance / \
* 4(B) 12(R) => 4(B) 12(R) => 4(B) 12(B) 最终保持黑色节点数量依旧是1或者2个
* / \ \ \
* 10(B) 14(B) 14(R) 14(R)
*
* 1.2.1.2兄弟节点是红色
* 1.2.1.2.1 兄弟节点是红色,父节点一定是黑色,它一定有俩黑色子节点
* parent parent parent
* | | |
* 8(B) 兄弟节点置黑,兄弟左节点置红 8(B) 12(B)
* / \ 删除4 着色 \ 对8左旋 / \
* 4(B) 12(R) => 12(B) => 8(B) 14(B) 最终保持黑色节点数量依旧是2个
* / \ / \ \
* 10(B) 14(B)必然是黑色 10(R) 14(B) 10(R)
*
* 1.2.2被删除节点在父节点的右数上
*
* 1.2.2.1兄弟节点是黑色
*
* 1.2.2.1.1 兄弟节点是黑色,且有一个左节点,左节点必然是红色 跟 1.2.1.1.1互为镜像
* parent parent parent
* | | |
* 8(可红可黑) 把父节点颜色赋值给3 8(可红可黑) 4(B)
* / \ 删除12 着色 / 对8右旋 / \
* 4(B) 12(B) => 4(B) => 3(可红可黑) 8(可红可黑) 最终保持黑色节点数量依旧是1或者2个
* / /
* 3(R)必然是红色 3(可红可黑)
*
* 1.2.2.1.2 兄弟节点是黑色,且有一个左节点,左节点必然是红色
* parent parent parent
* | 把父节点颜色赋值给兄弟节点 | |
* 8(可红可黑) 类似插入时候如右图 兄右置黑 8(可红可黑) 5(B)
* / \ 删除12 着色 转变为1.2.2.1.1 / 对8右旋 / \
* 4(B) 12(B) => 5(B) => 4(可红可黑) 8(可红可黑) 最终保持黑色节点数量依旧是1或者2个
* \ /
* 5(R)必然是红色 4(可红可黑)
*
* 1.2.2.1.3 兄弟节点是黑色,且有俩节点,必然都是红色
* parent parent parent
* | 把父节点颜色赋值给兄弟节点 | |
* 8(可红可黑) 把兄弟节点的左节点置黑 8(B) 4(可红可黑)
* / \ 把父节点置黑 删除12 / 对8右旋 / \
* 4(B) 12(B) => 4(可红可黑) => 1(B) 8(B) 最终保持黑色节点数量依旧是1或者2个
* / \ / \ /
* 1(R) 5(R)必然都是红色 1(R) 5(R) 5(R)
*
* 1.2.2.1.4 兄弟节点是黑色,且没有节点 黑色路径必然要-1了 递归
* ps:这个存疑 1.理论上插入时候每次自平衡不该有这个情况;2.即使有这个情况,那删除自身后,也不影响平衡啊
*
* (此处例外,不是删除12,而是删除5节点)
* parent parent parent
* | | |
* 8(可红可黑) 删除5(黑) 8(可红可黑) 8(可红可黑)
* / \ 把1置红 下一步rebalance / \ rebalance / \
* 4(R) 12(B) => 4(R) 12(B) => 4(B) 12(B) 最终保持黑色节点数量依旧是1或者2个
* / \ / /
* 1(B) 5(B)必然都是黑色 1(R) 1(R)
*
* 1.2.2.2兄弟节点是红色
* 1.2.2.2.1 兄弟节点是红色,父节点一定是黑色,它一定有俩黑色子节点
* parent parent parent
* | | |
* 8(B) 兄弟节点置黑,兄弟右节点置红 8(B) 4(B)
* / \ 删除12 着色 / 对8右左旋 / \
* 4(R) 12(B) => 4(B) => 1(B) 8(B) 最终保持黑色节点数量依旧是2个
* / \ / \ /
* 1(B) 5(B)必然是黑色 1(B) 5(R) 5(R)
*
*2. 只有左节点
* parent parent
* | |
* 8(可红可黑) 1的值赋给4 8(可红可黑)
* / \ 删除1 着色 / \
* 4(B) 12(B) => 1(B) 12(B) 最终保持黑色节点数量依旧是2个
* /
* 1(R)
*4. 只有右节点 同上
*5. 左右都有
* //后继节点:删除节点的右子树中的最小节点,即右子树中最左节点。
* //前驱节点:删除节点的左子树中最大节点,即左子树中最右节点。
* 使用前驱or后继代替当前删除节点,然后删除替代结点,把情形转化为1,2,3的情况
*/
8 红黑树删除代码RBTreeNode *FindMin(RBTreeNode *root)
{
if (NULL == root)
{
return NULL;
}
if (root->left == NULL)
{
return root;
}else{
return FindMin(root->left);
}
}
RBTreeNode *Delete(RBTreeNode *root, int target, RBTreeNode *rootNode)
{
if (NULL == root)
{
return NULL;
}
if (target > root->data)
{
rootNode = Delete(root->right, target, rootNode);
}else if(target < root->data){
rootNode = Delete(root->left, target, rootNode);
}else{
//根节点
if (root->parent == NULL)
{
return NULL;//删除自身
}
RBTreeNode *parent, *brother;
parent = root->parent;
int root_flag = 0;
if (parent == rootNode)
{
root_flag = 1;
}
//1.没有左右节点
if (root->left == NULL && root->right == NULL)
{
//1.1被删除节点是红色,直接删除即可
if (root->color == 1)
{
if (root == parent->left){
parent->left = NULL;
}else{
parent->right = NULL;
}
root = NULL;//删除自身
}else{
//1.2被删除节点是黑色,一定右兄弟节点 破坏了平衡性 需要重新平衡
//1.2.1被删除节点在父节点的左数上
if (root == parent->left)
{
root = NULL;
parent->left = NULL;//删除自身
brother = parent->right;
//1.2.1.1兄弟节点是黑色
if (brother->color == 0)
{
//1.2.1.1.1 兄弟节点是黑色,且有一个右节点,右节点必然是红色
if (brother->right != NULL && brother->left == NULL)
{
//把父亲颜色赋值给兄弟节点的右节点
brother->right->color = parent->color;
parent = left_rotation(parent);
}else if (brother->right == NULL && brother->left != NULL)
//1.2.1.1.2 兄弟节点是黑色,且有一个左节点,左节点必然是红色
{
//把父亲颜色赋值给兄弟节点
brother->color = parent->color;
parent->right = brother->left;
brother->parent = brother->left;
brother->left->parent = parent;
brother->left->right = brother;
brother->left = NULL;
parent = left_rotation(parent);
}else if (brother->right != NULL && brother->left != NULL)
{
//1.2.1.1.3 兄弟节点是黑色,且有俩节点,必然都是红色
//把父亲颜色赋值给兄弟节点
brother->color = parent->color;
//把兄弟节点的右节点置黑
//把父节点置黑
brother->right->color = 0;
parent->color = 0;
parent = left_rotation(parent);
}else{
//1.2.1.1.4 兄弟节点是黑色,且没有节点 黑色路径必然要-1了 递归
//ps:这个存疑 1.理论上插入时候每次自平衡不该有这个情况;2.即使有这个情况,那删除自身后,也不影响平衡啊
//parent->right->color = 1;
//return rebalance3(parent->right,rootNode);
}
}else{
//1.2.1.2兄弟节点是红色,父节点一定是黑色,它一定有俩黑色子节点
//兄弟节点置黑,兄弟左节点置红
brother->color = 0;
brother->left->color = 1;
parent = left_rotation(parent);
}
}else{
//1.2.2被删除节点在父节点的右数上
root = NULL;
parent->right = NULL;//删除自身
brother = parent->left;
//1.2.2.1 兄弟节点是黑色
if (brother->color == 0)
{
//1.2.2.1.1 兄弟节点是黑色,且有一个左节点,左节点必然是红色 跟1.2.1.1.1是镜像关系
if (brother->right == NULL && brother->left != NULL)
{
//把父亲颜色赋值给兄弟节点的左节点
brother->left->color = parent->color;
parent = right_rotation(parent);
}else if(brother->right != NULL && brother->left == NULL)
//1.2.2.1.2 兄弟节点是黑色,且有一个右节点,右节点必然是红色 跟1.2.1.1.2是镜像关系
{
parent->left = brother->right;
brother->color = parent->color;
brother->parent = brother->right;
brother->right->parent = parent;
brother->right->left = brother;
brother->right = NULL;
parent = right_rotation(parent);
}else if(brother->right != NULL && brother->left != NULL)
//1.2.2.1.3 兄弟节点是黑色,且有俩节点,必然都是红色 跟1.2.1.1.3是镜像关系
{
brother->left->color = 0;
brother->color = parent->color;
parent = right_rotation(parent);
}else{
//1.2.2.1.4 兄弟节点是黑色,且没有节点 黑色路径必然要-1了 递归
//ps:这个存疑 1.理论上插入时候每次自平衡不该有这个情况;2.即使有这个情况,那删除自身后,也不影响平衡啊
//do nothng
// parent->left->color = 1;
// return rebalance3(parent->left,rootNode);
}
}else{
//1.2.2.2兄弟节点是红色,父节点一定是黑色,它一定有俩黑色子节点
//兄弟节点置黑,兄弟右节点置红
brother->color = 0;
brother->right->color = 1;
parent = right_rotation(parent);
}
}
}
}else if (root->left != NULL && root->right == NULL)
//2.只有左节点 该左节点必然是红色,那root一定是黑色,root值替换为左节点的值,删除左节点
{
root->data = root->left->data;
root->left = NULL;
}else if (root->right != NULL && root->left == NULL)
//3.只有右节点 该右节点必然是红色,那root一定是黑色,root值替换为右节点的值,删除右节点
{
root->data = root->right->data;
root->right = NULL;
}else{
//4.左右都有的情况
//后继节点:删除节点的右子树中的最小节点,即右子树中最左节点。
//前驱节点:删除节点的左子树中最大节点,即左子树中最右节点。
//4.1使用后继节点作为代替结点
RBTreeNode *min = FindMin(root->right);
root->data = min->data;
rootNode = Delete(min, min->data, rootNode);
}
if (root_flag == 1)
{
return parent;
}
}
return rootNode;
}
* 删除测试代码int main()
{
struct RBTreeNode *node;
//1.1 测试用例
node = NULL;
node = inserRB(node, 8, NULL);
node = inserRB(node, 4, NULL);
node = Delete(node, 4, node);
printf("***1.1 测试用例 前序***: \n");
preOrderTraverse(node);
//1.2.1.1.1 测试用例
node = NULL;
node = inserRB(node, 8, NULL);
node = inserRB(node, 4, NULL);
node = inserRB(node, 12, NULL);
node = inserRB(node, 14, NULL);
node = Delete(node, 4, node);
printfNode(node);
printf("***1.2.1.1.1 测试用例 前序***: \n");
preOrderTraverse(node);
//1.2.1.1.2 测试用例
node = NULL;
node = inserRB(node, 8, NULL);
node = inserRB(node, 4, NULL);
node = inserRB(node, 12, NULL);
node = inserRB(node, 10, NULL);
node = Delete(node, 4, node);
printfNode(node);
printf("***1.2.1.1.2 测试用例 前序***: \n");
preOrderTraverse(node);
//1.2.1.1.3 测试用例
node = NULL;
node = inserRB(node, 8, NULL);
node = inserRB(node, 4, NULL);
node = inserRB(node, 12, NULL);
node = inserRB(node, 10, NULL);
node = inserRB(node, 14, NULL);
node = Delete(node, 4, node);
printfNode(node);
printf("***1.2.1.1.3 测试用例 前序***: \n");
preOrderTraverse(node);
//1.2.1.1.4 测试用例 存疑
node = NULL;
node = inserRB(node, 8, NULL);
node = inserRB(node, 4, NULL);
node = inserRB(node, 12, NULL);
node = inserRB(node, 10, NULL);
node = inserRB(node, 14, NULL);
//这里需要特殊处理,因为8,4,12,10,14生成的红黑树不符合1.2.1.1.4的测试场景,处理后依然是红黑树
// 8(B) 8(B)
// / \ 处理后 / \
// 4(B) 12(B) => 4(B) 12(R)
// / \ / \
// 10(R) 14(R) 10(B) 14(B)
node->right->color = 1;
node->right->right->color = 0;
node->right->left->color = 0;
node = Delete(node, 10, node);
printf("***1.2.1.1.4 测试用例 前序***: \n");
preOrderTraverse(node);
//1.2.1.2.1 测试用例 存疑
node = NULL;
node = inserRB(node, 8, NULL);
node = inserRB(node, 4, NULL);
node = inserRB(node, 12, NULL);
node = inserRB(node, 10, NULL);
node = inserRB(node, 14, NULL);
//这里需要特殊处理,因为8,4,12,10,14生成的红黑树不符合1.2.1.1.4的测试场景,处理后依然是红黑树
// 8(B) 8(B)
// / \ 处理后 / \
// 4(B) 12(B) => 4(B) 12(R)
// / \ / \
// 10(R) 14(R) 10(B) 14(B)
node->right->color = 1;
node->right->right->color = 0;
node->right->left->color = 0;
node = Delete(node, 4, node);
printf("***1.2.1.2.1 测试用例 前序***: \n");
preOrderTraverse(node);
//1.2.2.1.1 测试用例 跟1.2.1.1.1是镜像关系
node = NULL;
node = inserRB(node, 8, NULL);
node = inserRB(node, 4, NULL);
node = inserRB(node, 12, NULL);
node = inserRB(node, 3, NULL);
node = Delete(node, 12, node);
printfNode(node);
printf("***1.2.2.1.1 测试用例 前序***: \n");
preOrderTraverse(node);
//1.2.2.1.2 测试用例 跟1.2.1.1.2是镜像关系
node = NULL;
node = inserRB(node, 8, NULL);
node = inserRB(node, 4, NULL);
node = inserRB(node, 12, NULL);
node = inserRB(node, 5, NULL);
node = Delete(node, 12, node);
printfNode(node);
printf("***1.2.2.1.1 测试用例 前序***: \n");
preOrderTraverse(node);
//1.2.2.1.3 测试用例 跟1.2.1.1.2是镜像关系
node = NULL;
node = inserRB(node, 8, NULL);
node = inserRB(node, 4, NULL);
node = inserRB(node, 12, NULL);
node = inserRB(node, 1, NULL);
node = inserRB(node, 5, NULL);
node = Delete(node, 12, node);
printf("***1.2.2.1.3 测试用例 前序***: \n");
preOrderTraverse(node);
//1.2.2.1.4 测试用例 跟1.2.1.1.4是镜像关系 存疑
node = NULL;
node = inserRB(node, 8, NULL);
node = inserRB(node, 4, NULL);
node = inserRB(node, 12, NULL);
node = inserRB(node, 1, NULL);
node = inserRB(node, 5, NULL);
node = Delete(node, 5, node);
printf("***1.2.2.1.4 测试用例 前序***: \n");
preOrderTraverse(node);
//1.2.2.2 测试用例 跟1.2.2.1是镜像关系
node = NULL;
node = inserRB(node, 8, NULL);
node = inserRB(node, 4, NULL);
node = inserRB(node, 12, NULL);
node = inserRB(node, 1, NULL);
node = inserRB(node, 5, NULL);
//特殊处理
node->left->color = 1;
node->left->left->color = 0;
node->left->right->color = 0;
node = Delete(node, 12, node);
printf("***1.2.2.1.4 测试用例 前序***: \n");
preOrderTraverse(node);
//2 测试用例
node = NULL;
node = inserRB(node, 8, NULL);
node = inserRB(node, 4, NULL);
node = inserRB(node, 12, NULL);
node = inserRB(node, 3, NULL);
node = Delete(node, 4, node);
printf("***2 测试用例 前序***: \n");
preOrderTraverse(node);
//3 测试用例
node = NULL;
node = inserRB(node, 8, NULL);
node = inserRB(node, 2, NULL);
node = inserRB(node, 14, NULL);
node = inserRB(node, 1, NULL);
node = inserRB(node, 5, NULL);
node = inserRB(node, 12, NULL);
node = inserRB(node, 10, NULL);
node = inserRB(node, 28, NULL);
node = inserRB(node, 20, NULL);
node = inserRB(node, 40, NULL);
node = inserRB(node, 22, NULL);
node = Delete(node, 20, node);
printf("***3 测试用例 前序***: \n");
preOrderTraverse(node);
}
结果