树-排序二叉树删除

相比较节点的添加,平衡二叉树的删除要复杂一些。因为在删除的过程中,你要考虑到不同的情况,针对每一种不同的情况,你要有针对性的反应和调整。所以在代码编写的过程中,我们可以一边写代码,一边写测试用例。编写测试用例不光可以验证我们编写的代码是否正确,还能不断提高我们开发代码的自信心。这样,即使我们在开发过程对代码进行修改或者优化也不会担心害怕。然而看起来编写测试用例是一个繁杂的过程,但是从长期的收益来看,编写测试用例的成本是非常低廉的。

    在排序二叉树的删除过程当中,我们应该怎么做呢?大家不用担心,只要按照我们下面的介绍一步一步往下做就可以了,大体上分为下面三个步骤:

    1)判断参数的合法性,判断参数是否在当前的二叉树当中

    2)删除的节点是根节点,此时应该怎么调整

    3)删除的节点是普通节点,此时又应该怎么调整

    闲话不多说,下面看看我们的代码是怎么设计的?

   1、判断参数的合法性,同时判断当前的二叉树是否含有相关数据

    1.1 判断输入参数是否合法

[cpp]  view plain copy
  1. STATUS delete_node_from_tree(TREE_NODE** ppTreeNode, int data)  
  2. {  
  3.     if(NULL == ppTreeNode || NULL == *ppTreeNode)  
  4.         return FALSE;  
  5.     return TRUE;  
  6. }  
    那么此时测试用例怎么写呢?

[cpp]  view plain copy
  1. static void test1()  
  2. {  
  3.     TREE_NODE* pTreeNode = NULL;  
  4.     assert(FALSE == delete_node_from_tree(NULL, 10));  
  5.     assert(FALSE == delete_node_from_tree(&pTreeNode, 10));  
  6. }  
    注: 上面的测试用例说明当指针为空或者指针的指针为空,函数返回FALSE。

    1.2 判断输入数据是否存在

[cpp]  view plain copy
  1. STATUS delete_node_from_tree(TREE_NODE** ppTreeNode, int data)  
  2. {  
  3.     TREE_NODE* pTreeNode;  
  4.       
  5.     if(NULL == ppTreeNode || NULL == *ppTreeNode)  
  6.         return FALSE;  
  7.   
  8.     pTreeNode = find_data_in_tree_node(*ppTreeNode, data);  
  9.     if(NULL == pTreeNode)  
  10.         return FALSE;  
  11.       
  12.     return TRUE;  
  13. }  
    此时,我们设计一种当前指针合法,但是删除数据不存在的测试用例。

[cpp]  view plain copy
  1. static void test2()  
  2. {  
  3.     TREE_NODE* pTreeNode = NULL;  
  4.     pTreeNode = create_tree_node(10);  
  5.     assert(FALSE == delete_node_from_tree(&pTreeNode, 11));  
  6.     free(pTreeNode);  
  7. }  
    注: 上面的测试用例根节点为10,但是删除的数据为11,单步跟踪,验证我们编写的代码是否正确。


    2、删除的数据是根节点数据

    2.1 删除根数据时,根节点没有左子树,没有右子树情形

[cpp]  view plain copy
  1. /* 
  2. *                
  3. *         10          ======>    NULL 
  4. *        /  \ 
  5. *      NULL  NULL 
  6. */  
    那么此时代码应该怎么写呢?我们可以试一试。

[cpp]  view plain copy
  1. STATUS delete_node_from_tree(TREE_NODE** ppTreeNode, int data)  
  2. {  
  3.     TREE_NODE* pTreeNode;  
  4.       
  5.     if(NULL == ppTreeNode || NULL == *ppTreeNode)  
  6.         return FALSE;  
  7.   
  8.     pTreeNode = find_data_in_tree_node(*ppTreeNode, data);  
  9.     if(NULL == pTreeNode)  
  10.         return FALSE;  
  11.       
  12.     if(*ppTreeNode == pTreeNode){         
  13.         if(NULL == pTreeNode->left_child && NULL == pTreeNode->right_child){  
  14.             *ppTreeNode = NULL;  
  15.         }  
  16.           
  17.         free(pTreeNode);  
  18.         return TRUE;  
  19.     }  
  20.   
  21.     return TRUE;  
  22. }  
    我们的代码明显越来越长,我们要保持耐心。此时,该是我们添加新测试用例的时候了。

[cpp]  view plain copy
  1. static void test3()  
  2. {  
  3.     TREE_NODE* pTreeNode = NULL;  
  4.     pTreeNode = create_tree_node(10);  
  5.     assert(TRUE == delete_node_from_tree(&pTreeNode, 10));  
  6.     assert(NULL == pTreeNode);  
  7. }  
     2.2 删除根数据时,只有左子树节点,没有右子树节点
[cpp]  view plain copy
  1. /* 
  2. *                
  3. *         10          ======>    5 
  4. *        /  \                  /  \ 
  5. *      5  NULL                3    NULL 
  6. *     /                       
  7. *    3 
  8. */  
    很明显,我们只需要把用左子树节点代替原来的根节点即可。

[cpp]  view plain copy
  1. STATUS delete_node_from_tree(TREE_NODE** ppTreeNode, int data)  
  2. {  
  3.     TREE_NODE* pTreeNode;  
  4.       
  5.     if(NULL == ppTreeNode || NULL == *ppTreeNode)  
  6.         return FALSE;  
  7.   
  8.     pTreeNode = find_data_in_tree_node(*ppTreeNode, data);  
  9.     if(NULL == pTreeNode)  
  10.         return FALSE;  
  11.       
  12.     if(*ppTreeNode == pTreeNode){         
  13.         if(NULL == pTreeNode->left_child && NULL == pTreeNode->right_child){  
  14.             *ppTreeNode = NULL;  
  15.         }else if(NULL != pTreeNode->left_child && NULL == pTreeNode->right_child){  
  16.             *ppTreeNode = pTreeNode->left_child;  
  17.             pTreeNode->left_child->parent = NULL;  
  18.         }  
  19.           
  20.         free(pTreeNode);  
  21.         return TRUE;  
  22.     }  
  23.   
  24.     return TRUE;  
  25. }  
    这个时候,我们可以添加新的测试用例,分别添加10、5、3,然后删除10。

[cpp]  view plain copy
  1. static void test4()  
  2. {  
  3.     TREE_NODE* pTreeNode = NULL;  
  4.     assert(TRUE == insert_node_into_tree(&pTreeNode, 10));  
  5.     assert(TRUE == insert_node_into_tree(&pTreeNode, 5));  
  6.     assert(TRUE == insert_node_into_tree(&pTreeNode, 3));  
  7.     assert(TRUE == delete_node_from_tree(&pTreeNode, 10));  
  8.     assert(5 == pTreeNode->data);  
  9.     assert(NULL == pTreeNode->parent);  
  10.     free(pTreeNode->left_child);  
  11.     free(pTreeNode);  
  12. }  
     2 .3 删除根数据时,没有左子树节点,只有右子树节点

[cpp]  view plain copy
  1. /* 
  2. *                
  3. *         10          ======>    15 
  4. *        /  \                   /   \ 
  5. *     NULL  15               NULL    20 
  6. *             \ 
  7. *             20 
  8. */  
    上面的代码表示了节点的删除过程。我们可以按照这个流程编写代码。

[cpp]  view plain copy
  1. STATUS delete_node_from_tree(TREE_NODE** ppTreeNode, int data)  
  2. {  
  3.     TREE_NODE* pTreeNode;  
  4.       
  5.     if(NULL == ppTreeNode || NULL == *ppTreeNode)  
  6.         return FALSE;  
  7.   
  8.     pTreeNode = find_data_in_tree_node(*ppTreeNode, data);  
  9.     if(NULL == pTreeNode)  
  10.         return FALSE;  
  11.       
  12.     if(*ppTreeNode == pTreeNode){         
  13.         if(NULL == pTreeNode->left_child && NULL == pTreeNode->right_child){  
  14.             *ppTreeNode = NULL;  
  15.         }else if(NULL != pTreeNode->left_child && NULL == pTreeNode->right_child){  
  16.             *ppTreeNode = pTreeNode->left_child;  
  17.             pTreeNode->left_child->parent = NULL;  
  18.         }else if(NULL == pTreeNode->left_child && NULL != pTreeNode->right_child){  
  19.             *ppTreeNode = pTreeNode->right_child;  
  20.             pTreeNode->right_child->parent = NULL;  
  21.         }  
  22.           
  23.         free(pTreeNode);  
  24.         return TRUE;  
  25.     }  
  26.   
  27.     return TRUE;  
  28. }  
    添加测试用例,依次添加10、15、20,然后删除数据10。

[cpp]  view plain copy
  1. static void test5()  
  2. {  
  3.     TREE_NODE* pTreeNode = NULL;  
  4.     assert(TRUE == insert_node_into_tree(&pTreeNode, 10));  
  5.     assert(TRUE == insert_node_into_tree(&pTreeNode, 15));  
  6.     assert(TRUE == insert_node_into_tree(&pTreeNode, 20));  
  7.     assert(TRUE == delete_node_from_tree(&pTreeNode, 10));  
  8.     assert(15 == pTreeNode->data);  
  9.     assert(NULL == pTreeNode->parent);  
  10.     free(pTreeNode->right_child);  
  11.     free(pTreeNode);  
  12. }  

    2.4删除数据的左右节点都存在

  2.4 删除节点的左右子树都存在,此时又会分成两种情形

    1)左节点是当前左子树的最大节点,此时只需要用左节点代替根节点即可

[cpp]  view plain copy
  1. /* 
  2. *                
  3. *         10          ======>     6 
  4. *        /  \                   /   \ 
  5. *      6     15               5     15 
  6. *     /                       
  7. *    5                          
  8. */  
    代码该怎么编写呢?

[cpp]  view plain copy
  1. STATUS delete_node_from_tree(TREE_NODE** ppTreeNode, int data)  
  2. {  
  3.     TREE_NODE* pTreeNode;  
  4.     TREE_NODE* pLeftMax;  
  5.       
  6.     if(NULL == ppTreeNode || NULL == *ppTreeNode)  
  7.         return FALSE;  
  8.       
  9.     pTreeNode = find_data_in_tree_node(*ppTreeNode, data);  
  10.     if(NULL == pTreeNode)  
  11.         return FALSE;  
  12.       
  13.     if(*ppTreeNode == pTreeNode){  
  14.           
  15.         if(NULL == pTreeNode->left_child && NULL == pTreeNode->right_child){  
  16.             *ppTreeNode = NULL;  
  17.         }else if(NULL != pTreeNode->left_child && NULL == pTreeNode->right_child){  
  18.             *ppTreeNode = pTreeNode->left_child;  
  19.             pTreeNode->left_child->parent = NULL;  
  20.         }else if(NULL == pTreeNode->left_child && NULL != pTreeNode->right_child){  
  21.             *ppTreeNode = pTreeNode->right_child;  
  22.             pTreeNode->right_child->parent = NULL;  
  23.         }else{  
  24.             pLeftMax = find_max_node(pTreeNode->left_child);  
  25.             if(pLeftMax == pTreeNode->left_child){  
  26.                 *ppTreeNode = pTreeNode->left_child;  
  27.                 (*ppTreeNode)->right_child = pTreeNode->right_child;  
  28.                 (*ppTreeNode)->right_child->parent = *ppTreeNode;  
  29.                 (*ppTreeNode)->parent = NULL;  
  30.             }  
  31.         }  
  32.           
  33.         free(pTreeNode);  
  34.         return TRUE;  
  35.     }  
  36.       
  37.     return TRUE;  
  38. }  
    上面的代码中添加的内容表示了我们介绍的这一情形。为此,我们可以设计一种测试用例。依次插入10、6、5、15,然后删除10即可。

[cpp]  view plain copy
  1. static void test6()  
  2. {  
  3.     TREE_NODE* pTreeNode = NULL;  
  4.     assert(TRUE == insert_node_into_tree(&pTreeNode, 10));  
  5.     assert(TRUE == insert_node_into_tree(&pTreeNode, 6));  
  6.     assert(TRUE == insert_node_into_tree(&pTreeNode, 5));  
  7.     assert(TRUE == insert_node_into_tree(&pTreeNode, 15));  
  8.     assert(TRUE == delete_node_from_tree(&pTreeNode, 10));  
  9.     assert(6 == pTreeNode->data);  
  10.     assert(NULL == pTreeNode->parent);  
  11.     assert(15 == pTreeNode->right_child->data);  
  12.     assert(pTreeNode = pTreeNode->right_child->parent);  
  13.     assert(NULL == pTreeNode->parent);  
  14.     free(pTreeNode->left_child);  
  15.     free(pTreeNode->right_child);  
  16.     free(pTreeNode);  
  17. }  
    如果上面的测试用例通过,表示我们添加的代码没有问题。


    2)左节点不是当前左子树的最大节点,情形如下所示

[cpp]  view plain copy
  1. /* 
  2. *                
  3. *         10          ======>     8 
  4. *        /  \                   /   \ 
  5. *      6     15               5     15 
  6. *       \                       
  7. *        8                      
  8. */  
    此时,我们应该用10左侧的最大节点8代替删除的节点10即可。

[cpp]  view plain copy
  1. STATUS delete_node_from_tree(TREE_NODE** ppTreeNode, int data)  
  2. {  
  3.     TREE_NODE* pTreeNode;  
  4.     TREE_NODE* pLeftMax;  
  5.       
  6.     if(NULL == ppTreeNode || NULL == *ppTreeNode)  
  7.         return FALSE;  
  8.       
  9.     pTreeNode = find_data_in_tree_node(*ppTreeNode, data);  
  10.     if(NULL == pTreeNode)  
  11.         return FALSE;  
  12.       
  13.     if(*ppTreeNode == pTreeNode){  
  14.           
  15.         if(NULL == pTreeNode->left_child && NULL == pTreeNode->right_child){  
  16.             *ppTreeNode = NULL;  
  17.         }else if(NULL != pTreeNode->left_child && NULL == pTreeNode->right_child){  
  18.             *ppTreeNode = pTreeNode->left_child;  
  19.             pTreeNode->left_child->parent = NULL;  
  20.         }else if(NULL == pTreeNode->left_child && NULL != pTreeNode->right_child){  
  21.             *ppTreeNode = pTreeNode->right_child;  
  22.             pTreeNode->right_child->parent = NULL;  
  23.         }else{  
  24.             pLeftMax = find_max_node(pTreeNode->left_child);  
  25.             if(pLeftMax == pTreeNode->left_child){  
  26.                 *ppTreeNode = pTreeNode->left_child;  
  27.                 (*ppTreeNode)->right_child = pTreeNode->right_child;  
  28.                 (*ppTreeNode)->right_child->parent = *ppTreeNode;  
  29.                 (*ppTreeNode)->parent = NULL;  
  30.             }else{  
  31.                 pTreeNode->data = pLeftMax->data;  
  32.                 pLeftMax->parent->right_child = NULL;  
  33.                 pTreeNode = pLeftMax;  
  34.             }  
  35.         }  
  36.           
  37.         free(pTreeNode);  
  38.         return TRUE;  
  39.     }  
  40.       
  41.     return TRUE;  
  42. }  
    那么,这个场景下面测试用例又该怎么设计呢?其实只需要按照上面给出的示意图进行即可。依次插入数据10、6、8、15,然后删除数据10。

[cpp]  view plain copy
  1. static void test7()  
  2. {  
  3.     TREE_NODE* pTreeNode = NULL;  
  4.     assert(TRUE == insert_node_into_tree(&pTreeNode, 10));  
  5.     assert(TRUE == insert_node_into_tree(&pTreeNode, 6));  
  6.     assert(TRUE == insert_node_into_tree(&pTreeNode, 8));  
  7.     assert(TRUE == insert_node_into_tree(&pTreeNode, 15));  
  8.     assert(TRUE == delete_node_from_tree(&pTreeNode, 10));  
  9.     assert(8 == pTreeNode->data);  
  10.     assert(NULL == pTreeNode->parent);  
  11.     assert(NULL == pTreeNode->left_child->right_child);  
  12.     assert(NULL == pTreeNode->parent);  
  13.     free(pTreeNode->left_child);  
  14.     free(pTreeNode->right_child);  
  15.     free(pTreeNode);  
  16. }  
    至此,删除节点为根节点的情形全部讨论完毕,那么如果删除的节点是普通节点呢,那应该怎么解决呢?

[cpp]  view plain copy
  1. STATUS delete_node_from_tree(TREE_NODE** ppTreeNode, int data)  
  2. {  
  3.     TREE_NODE* pTreeNode;  
  4.     TREE_NODE* pLeftMax;  
  5.       
  6.     if(NULL == ppTreeNode || NULL == *ppTreeNode)  
  7.         return FALSE;  
  8.       
  9.     pTreeNode = find_data_in_tree_node(*ppTreeNode, data);  
  10.     if(NULL == pTreeNode)  
  11.         return FALSE;  
  12.       
  13.     if(*ppTreeNode == pTreeNode){  
  14.           
  15.         if(NULL == pTreeNode->left_child && NULL == pTreeNode->right_child){  
  16.             *ppTreeNode = NULL;  
  17.         }else if(NULL != pTreeNode->left_child && NULL == pTreeNode->right_child){  
  18.             *ppTreeNode = pTreeNode->left_child;  
  19.             pTreeNode->left_child->parent = NULL;  
  20.         }else if(NULL == pTreeNode->left_child && NULL != pTreeNode->right_child){  
  21.             *ppTreeNode = pTreeNode->right_child;  
  22.             pTreeNode->right_child->parent = NULL;  
  23.         }else{  
  24.             pLeftMax = find_max_node(pTreeNode->left_child);  
  25.             if(pLeftMax == pTreeNode->left_child){  
  26.                 *ppTreeNode = pTreeNode->left_child;  
  27.                 (*ppTreeNode)->right_child = pTreeNode->right_child;  
  28.                 (*ppTreeNode)->right_child->parent = *ppTreeNode;  
  29.                 (*ppTreeNode)->parent = NULL;  
  30.             }else{  
  31.                 pTreeNode->data = pLeftMax->data;  
  32.                 pLeftMax->parent->right_child = pLeftMax->left_child;  
  33.                 pLeftMax->left_child->parent = pLeftMax->parent;  
  34.                 pTreeNode = pLeftMax;  
  35.             }  
  36.         }  
  37.           
  38.         free(pTreeNode);  
  39.         return TRUE;  
  40.     }  
  41.       
  42.     return _delete_node_from_tree(pTreeNode);  
  43. }  
    我们在当前函数的最后一行添加_delete_node_from_tree,这个函数用来处理普通节点的删除情况,我们会在下面一篇博客中继续介绍。


    3、 普通节点的删除

3.1 删除的节点没有左子树,也没有右子树

     测试用例1: 删除节点6

[cpp]  view plain copy
  1. /* 
  2. *                
  3. *         10          ======>     10 
  4. *        /  \                      \ 
  5. *      6     15                     15 
  6. *                                                          
  7. */  
  8.   
  9. static void test8()  
  10. {  
  11.     TREE_NODE* pTreeNode = NULL;  
  12.     assert(TRUE == insert_node_into_tree(&pTreeNode, 10));  
  13.     assert(TRUE == insert_node_into_tree(&pTreeNode, 6));  
  14.     assert(6 == pTreeNode->left_child->data);  
  15.     assert(TRUE == insert_node_into_tree(&pTreeNode, 15));  
  16.     assert(TRUE == delete_node_from_tree(&pTreeNode, 6));  
  17.     assert(NULL == pTreeNode->left_child);  
  18.     free(pTreeNode->right_child);  
  19.     free(pTreeNode);  
  20. }  
    测试用例2: 删除节点15

[cpp]  view plain copy
  1. /* 
  2. *                
  3. *         10          ======>     10 
  4. *        /  \                    /  
  5. *      6     15                 6    
  6. *                                                          
  7. */  
  8.   
  9. static void test9()  
  10. {  
  11.     TREE_NODE* pTreeNode = NULL;  
  12.     assert(TRUE == insert_node_into_tree(&pTreeNode, 10));  
  13.     assert(TRUE == insert_node_into_tree(&pTreeNode, 6));  
  14.     assert(TRUE == insert_node_into_tree(&pTreeNode, 15));  
  15.     assert(15 == pTreeNode->right_child->data);  
  16.     assert(TRUE == delete_node_from_tree(&pTreeNode, 15));  
  17.     assert(NULL == pTreeNode->right_child);  
  18.     free(pTreeNode->right_child);  
  19.     free(pTreeNode);  
  20. }  
    那么代码应该怎么编写呢?

[cpp]  view plain copy
  1. STATUS _delete_node_from_tree(TREE_NODE* pTreeNode)  
  2. {  
  3.     TREE_NODE* pLeftMax;  
  4.       
  5.     if(NULL == pTreeNode-> left_child && NULL == pTreeNode->right_child){  
  6.         if(pTreeNode == pTreeNode->parent->left_child)  
  7.             pTreeNode->parent->left_child = NULL;  
  8.         else  
  9.             pTreeNode->parent->right_child = NULL;  
  10.     }  
  11.       
  12.     free(pTreeNode);  
  13.     return TRUE;  
  14. }  

     3.2 删除的节点有左子树,没有右子树

    测试用例1: 测试节点6

[cpp]  view plain copy
  1. /* 
  2. *                
  3. *         10          ======>     10 
  4. *        /                      /  
  5. *      6                      3    
  6. *     / 
  7. *    3                                                         
  8. */  
  9.   
  10. static void test10()  
  11. {  
  12.     TREE_NODE* pTreeNode = NULL;  
  13.     assert(TRUE == insert_node_into_tree(&pTreeNode, 10));  
  14.     assert(TRUE == insert_node_into_tree(&pTreeNode, 6));  
  15.     assert(TRUE == insert_node_into_tree(&pTreeNode, 3));  
  16.     assert(TRUE == delete_node_from_tree(&pTreeNode, 6));  
  17.     assert(3 == pTreeNode->left_child->data);  
  18.     assert(pTreeNode = pTreeNode->left_child->parent);  
  19.     free(pTreeNode->left_child);  
  20.     free(pTreeNode);  
  21. }  
    测试用例2: 删除节点15

[cpp]  view plain copy
  1. /* 
  2. *                
  3. *         10          ======>     10 
  4. *           \                       \ 
  5. *           15                       12 
  6. *            /                     
  7. *           12                                                  
  8. */  
  9.   
  10. static void test11()  
  11. {  
  12.     TREE_NODE* pTreeNode = NULL;  
  13.     assert(TRUE == insert_node_into_tree(&pTreeNode, 10));  
  14.     assert(TRUE == insert_node_into_tree(&pTreeNode, 15));  
  15.     assert(TRUE == insert_node_into_tree(&pTreeNode, 12));  
  16.     assert(TRUE == delete_node_from_tree(&pTreeNode, 15));  
  17.     assert(12 == pTreeNode->right_child->data);  
  18.     assert(pTreeNode = pTreeNode->right_child->parent);  
  19.     free(pTreeNode->right_child);  
  20.     free(pTreeNode);  
  21. }  
    添加左子树不为空,右子树为空的处理代码,如下所示:

[cpp]  view plain copy
  1. STATUS _delete_node_from_tree(TREE_NODE* pTreeNode)  
  2. {  
  3.     TREE_NODE* pLeftMax;  
  4.       
  5.     if(NULL == pTreeNode-> left_child && NULL == pTreeNode->right_child){  
  6.         if(pTreeNode == pTreeNode->parent->left_child)  
  7.             pTreeNode->parent->left_child = NULL;  
  8.         else  
  9.             pTreeNode->parent->right_child = NULL;  
  10.     }else if(NULL != pTreeNode->left_child && NULL == pTreeNode->right_child){  
  11.         pTreeNode->left_child->parent = pTreeNode->parent;  
  12.           
  13.         if(pTreeNode == pTreeNode->parent->left_child)  
  14.             pTreeNode->parent->left_child = pTreeNode->left_child;  
  15.         else  
  16.             pTreeNode->parent->right_child = pTreeNode->left_child;  
  17.     }  
  18.       
  19.     free(pTreeNode);  
  20.     return TRUE;  
  21. }  

     3.3 删除的节点左子树为空,右子树节点不为空

    测试用例1: 删除数据6

[cpp]  view plain copy
  1. /* 
  2. *                
  3. *         10          ======>    10 
  4. *        /                     /  
  5. *      6                      8    
  6. *       \ 
  7. *        8                                                     
  8. */  
  9.   
  10. static void test12()  
  11. {  
  12.     TREE_NODE* pTreeNode = NULL;  
  13.     assert(TRUE == insert_node_into_tree(&pTreeNode, 10));  
  14.     assert(TRUE == insert_node_into_tree(&pTreeNode, 6));  
  15.     assert(TRUE == insert_node_into_tree(&pTreeNode, 8));  
  16.     assert(TRUE == delete_node_from_tree(&pTreeNode, 6));  
  17.     assert(8 == pTreeNode->left_child->data);  
  18.     assert(pTreeNode = pTreeNode->left_child->parent);  
  19.     free(pTreeNode->left_child);  
  20.     free(pTreeNode);  
  21. }  
    测试用例2: 删除数据15

[cpp]  view plain copy
  1. /* 
  2. *                
  3. *        10          ======>    10 
  4. *          \                      \  
  5. *           15                     20  
  6. *             \ 
  7. *             20                                              
  8. */  
  9.   
  10. static void test13()  
  11. {  
  12.     TREE_NODE* pTreeNode = NULL;  
  13.     assert(TRUE == insert_node_into_tree(&pTreeNode, 10));  
  14.     assert(TRUE == insert_node_into_tree(&pTreeNode, 15));  
  15.     assert(TRUE == insert_node_into_tree(&pTreeNode, 20));  
  16.     assert(TRUE == delete_node_from_tree(&pTreeNode, 15));  
  17.     assert(20 == pTreeNode->right_child->data);  
  18.     assert(pTreeNode = pTreeNode->right_child->parent);  
  19.     free(pTreeNode->right_child);  
  20.     free(pTreeNode);  
  21. }  
    添加左子树为空,右子树不为空的处理情形。代码如下:

[cpp]  view plain copy
  1. STATUS _delete_node_from_tree(TREE_NODE* pTreeNode)  
  2. {  
  3.     TREE_NODE* pLeftMax;  
  4.       
  5.     if(NULL == pTreeNode-> left_child && NULL == pTreeNode->right_child){  
  6.         if(pTreeNode == pTreeNode->parent->left_child)  
  7.             pTreeNode->parent->left_child = NULL;  
  8.         else  
  9.             pTreeNode->parent->right_child = NULL;  
  10.     }else if(NULL != pTreeNode->left_child && NULL == pTreeNode->right_child){  
  11.         pTreeNode->left_child->parent = pTreeNode->parent;  
  12.           
  13.         if(pTreeNode == pTreeNode->parent->left_child)  
  14.             pTreeNode->parent->left_child = pTreeNode->left_child;  
  15.         else  
  16.             pTreeNode->parent->right_child = pTreeNode->left_child;  
  17.     }else if(NULL == pTreeNode->left_child && NULL != pTreeNode->right_child){  
  18.         pTreeNode->right_child->parent = pTreeNode->parent;  
  19.           
  20.         if(pTreeNode == pTreeNode->parent->left_child)  
  21.             pTreeNode->parent->left_child = pTreeNode->right_child;  
  22.         else  
  23.             pTreeNode->parent->right_child = pTreeNode->right_child;  
  24.     }  
  25.       
  26.     free(pTreeNode);  
  27.     return TRUE;  
  28. }  

    3.4 删除的节点左右子树均不为空,不过又要分为两种情形:

    1) 左节点是删除节点左侧的最大节点 (删除节点6)

[cpp]  view plain copy
  1. /* 
  2. *                
  3. *         10          ======>    10 
  4. *        /                     /  
  5. *      6                      5     
  6. *    /  \                      \ 
  7. *   5    8                      8                               
  8. */  
  9.   
  10. static void test14()  
  11. {  
  12.     TREE_NODE* pTreeNode = NULL;  
  13.     assert(TRUE == insert_node_into_tree(&pTreeNode, 10));  
  14.     assert(TRUE == insert_node_into_tree(&pTreeNode, 6));  
  15.     assert(TRUE == insert_node_into_tree(&pTreeNode, 5));  
  16.     assert(TRUE == insert_node_into_tree(&pTreeNode, 8));  
  17.     assert(TRUE == delete_node_from_tree(&pTreeNode, 6));  
  18.     assert(5 == pTreeNode->left_child->data);  
  19.     assert(pTreeNode = pTreeNode->left_child->parent);  
  20.     assert( 8 == pTreeNode->left_child->right_child->data);  
  21.     assert(pTreeNode->left_child = pTreeNode->left_child->right_child->parent);  
  22.     free(pTreeNode->left_child->right_child);  
  23.     free(pTreeNode->left_child);  
  24.     free(pTreeNode);  
  25. }  
     2) 左节点不是删除节点左侧的最大节点(删除节点5)

[cpp]  view plain copy
  1. /* 
  2. *                
  3. *         10          ======>    10 
  4. *        /                     /  
  5. *       5                      4     
  6. *      / \                    / \ 
  7. *     2   6                  2   6 
  8. *      \                                
  9. *       4 
  10. */  
  11.   
  12. static void test15()  
  13. {  
  14.     TREE_NODE* pTreeNode = NULL;  
  15.     assert(TRUE == insert_node_into_tree(&pTreeNode, 10));  
  16.     assert(TRUE == insert_node_into_tree(&pTreeNode, 5));  
  17.     assert(TRUE == insert_node_into_tree(&pTreeNode, 2));  
  18.     assert(TRUE == insert_node_into_tree(&pTreeNode, 4));  
  19.     assert(TRUE == insert_node_into_tree(&pTreeNode, 6));  
  20.     assert(TRUE == delete_node_from_tree(&pTreeNode, 5));  
  21.     assert(4 == pTreeNode->left_child->data);  
  22.     assert(NULL == pTreeNode->left_child->left_child->right_child);  
  23.     free(pTreeNode->left_child->left_child);  
  24.     free(pTreeNode->left_child->right_child);  
  25.     free(pTreeNode->left_child);  
  26.     free(pTreeNode);  
  27. }  
    那么针对这两种类型,我们的代码究竟应该怎么处理呢?

[cpp]  view plain copy
  1. STATUS _delete_node_from_tree(TREE_NODE* pTreeNode)  
  2. {  
  3.     TREE_NODE* pLeftMax;  
  4.       
  5.     if(NULL == pTreeNode-> left_child && NULL == pTreeNode->right_child){  
  6.         if(pTreeNode == pTreeNode->parent->left_child)  
  7.             pTreeNode->parent->left_child = NULL;  
  8.         else  
  9.             pTreeNode->parent->right_child = NULL;  
  10.     }else if(NULL != pTreeNode->left_child && NULL == pTreeNode->right_child){  
  11.         pTreeNode->left_child->parent = pTreeNode->parent;  
  12.           
  13.         if(pTreeNode == pTreeNode->parent->left_child)  
  14.             pTreeNode->parent->left_child = pTreeNode->left_child;  
  15.         else  
  16.             pTreeNode->parent->right_child = pTreeNode->left_child;  
  17.     }else if(NULL == pTreeNode->left_child && NULL != pTreeNode->right_child){  
  18.         pTreeNode->right_child->parent = pTreeNode->parent;  
  19.           
  20.         if(pTreeNode == pTreeNode->parent->left_child)  
  21.             pTreeNode->parent->left_child = pTreeNode->right_child;  
  22.         else  
  23.             pTreeNode->parent->right_child = pTreeNode->right_child;  
  24.     }else{  
  25.         pLeftMax = find_max_node(pTreeNode->left_child);  
  26.         if(pLeftMax == pTreeNode->left_child){  
  27.               
  28.             if(pTreeNode == pTreeNode->parent->left_child)  
  29.                 pTreeNode->parent->left_child = pTreeNode->left_child;  
  30.             else  
  31.                 pTreeNode->parent->right_child = pTreeNode->left_child;  
  32.               
  33.             pTreeNode->left_child->parent = pTreeNode->parent;  
  34.             pTreeNode->left_child->right_child = pTreeNode->right_child;  
  35.             pTreeNode->right_child->parent = pTreeNode-> left_child;  
  36.               
  37.         }else{  
  38.             pTreeNode->data = pLeftMax->data;  
  39.             pLeftMax->parent->right_child = pLeftMax->left_child;  
  40.             pLeftMax->left_child->parent = pLeftMax->parent;  
  41.             pTreeNode = pLeftMax;  
  42.         }  
  43.     }  
  44.       
  45.     free(pTreeNode);  
  46.     return TRUE;  
  47. }  

结束总结:


    上面的过程记录了我们的代码是怎么一步一步走过来的。最后我们给出一份完整的节点删除代码:

[cpp]  view plain copy
  1. STATUS _delete_node_from_tree(TREE_NODE* pTreeNode)  
  2. {  
  3.     TREE_NODE* pLeftMax;  
  4.       
  5.     if(NULL == pTreeNode-> left_child && NULL == pTreeNode->right_child){  
  6.         if(pTreeNode == pTreeNode->parent->left_child)  
  7.             pTreeNode->parent->left_child = NULL;  
  8.         else  
  9.             pTreeNode->parent->right_child = NULL;  
  10.     }else if(NULL != pTreeNode->left_child && NULL == pTreeNode->right_child){  
  11.         pTreeNode->left_child->parent = pTreeNode->parent;  
  12.           
  13.         if(pTreeNode == pTreeNode->parent->left_child)  
  14.             pTreeNode->parent->left_child = pTreeNode->left_child;  
  15.         else  
  16.             pTreeNode->parent->right_child = pTreeNode->left_child;  
  17.     }else if(NULL == pTreeNode->left_child && NULL != pTreeNode->right_child){  
  18.         pTreeNode->right_child->parent = pTreeNode->parent;  
  19.           
  20.         if(pTreeNode == pTreeNode->parent->left_child)  
  21.             pTreeNode->parent->left_child = pTreeNode->right_child;  
  22.         else  
  23.             pTreeNode->parent->right_child = pTreeNode->right_child;  
  24.     }else{  
  25.         pLeftMax = find_max_node(pTreeNode->left_child);  
  26.         if(pLeftMax == pTreeNode->left_child){  
  27.               
  28.             if(pTreeNode == pTreeNode->parent->left_child)  
  29.                 pTreeNode->parent->left_child = pTreeNode->left_child;  
  30.             else  
  31.                 pTreeNode->parent->right_child = pTreeNode->left_child;  
  32.               
  33.             pTreeNode->left_child->parent = pTreeNode->parent;  
  34.             pTreeNode->left_child->right_child = pTreeNode->right_child;  
  35.             pTreeNode->right_child->parent = pTreeNode-> left_child;  
  36.               
  37.         }else{  
  38.             pTreeNode->data = pLeftMax->data;  
  39.             pLeftMax->parent->right_child = pLeftMax->left_child;  
  40.             pLeftMax->left_child->parent = pLeftMax->parent;             
  41.             pTreeNode = pLeftMax;  
  42.         }  
  43.     }  
  44.       
  45.     free(pTreeNode);  
  46.     return TRUE;  
  47. }  
  48.   
  49. STATUS delete_node_from_tree(TREE_NODE** ppTreeNode, int data)  
  50. {  
  51.     TREE_NODE* pTreeNode;  
  52.     TREE_NODE* pLeftMax;  
  53.       
  54.     if(NULL == ppTreeNode || NULL == *ppTreeNode)  
  55.         return FALSE;  
  56.       
  57.     pTreeNode = find_data_in_tree_node(*ppTreeNode, data);  
  58.     if(NULL == pTreeNode)  
  59.         return FALSE;  
  60.       
  61.     if(*ppTreeNode == pTreeNode){  
  62.           
  63.         if(NULL == pTreeNode->left_child && NULL == pTreeNode->right_child){  
  64.             *ppTreeNode = NULL;  
  65.         }else if(NULL != pTreeNode->left_child && NULL == pTreeNode->right_child){  
  66.             *ppTreeNode = pTreeNode->left_child;  
  67.             pTreeNode->left_child->parent = NULL;  
  68.         }else if(NULL == pTreeNode->left_child && NULL != pTreeNode->right_child){  
  69.             *ppTreeNode = pTreeNode->right_child;  
  70.             pTreeNode->right_child->parent = NULL;  
  71.         }else{  
  72.             pLeftMax = find_max_node(pTreeNode->left_child);  
  73.             if(pLeftMax == pTreeNode->left_child){  
  74.                 *ppTreeNode = pTreeNode->left_child;  
  75.                 (*ppTreeNode)->right_child = pTreeNode->right_child;  
  76.                 (*ppTreeNode)->right_child->parent = *ppTreeNode;  
  77.                 (*ppTreeNode)->parent = NULL;  
  78.             }else{  
  79.                 pTreeNode->data = pLeftMax->data;  
  80.                 pLeftMax->parent->right_child = pLeftMax->left_child;  
  81.                 pLeftMax->left_child->parent = pLeftMax->parent;  
  82.                 pTreeNode = pLeftMax;  
  83.             }  
  84.         }  
  85.           
  86.         free(pTreeNode);  
  87.         return TRUE;  
  88.     }  
  89.       
  90.     return _delete_node_from_tree(pTreeNode);  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值