花了好幾天的業餘時間,看文章,總算是用C實現了一遍紅黑樹,主要仍是本身C語言水平不夠高,調試斷點浪費了很多時間,閒話少說node
//這裏偷懶就應0表明黑色,1表明紅色了 typedef struct RBTreeNode { int data; //數據域 int color; //0黑色 1紅色 struct RBTreeNode *parent;//父親結點 struct RBTreeNode *left; //左子結點 struct RBTreeNode *right; //右子結點 } RBTreeNode;
//這裏打印了節點的顏色和父節點 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); } }
跟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; }
/** * 右旋 * 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; }
/** * 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) * * */
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; }
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; }
RBTreeNode *inserRB(RBTreeNode *root, int data, RBTreeNode *parent) { root = insert(root,data,parent); return rebalance3(RBTreeEndNode,root); }
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); }
測試結果:
spa
*刪除 * *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了 遞歸 * ps:這個存疑 1.理論上插入時候每次自平衡不應有這個狀況;2.即便有這個狀況,那刪除自身後,也不影響平衡啊 * * (此處例外,不是刪除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的狀況 */
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); }