程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> 一步一步寫算法(之排序二叉樹刪除-2)

一步一步寫算法(之排序二叉樹刪除-2)

編輯:關於C語言

 

【 聲明:版權所有,歡迎轉載,請勿用於商業用途。  聯系信箱:feixiaoxing @163.com】

 

 

 

 

    2.4 刪除節點的左右子樹都存在,此時又會分成兩種情形

 

    1)左節點是當前左子樹的最大節點,此時只需要用左節點代替根節點即可

 

 

 

/*

*               

*         10          ======>     6

*        /  \                   /   \

*      6     15               5     15

*     /                      

*    5                         

*/ 

/*

*              

*         10          ======>     6

*        /  \                   /   \

*      6     15               5     15

*     /                      

*    5                        

*/    代碼該怎麼編寫呢?

 

 

STATUS delete_node_from_tree(TREE_NODE** ppTreeNode, int data) 

    TREE_NODE* pTreeNode; 

    TREE_NODE* pLeftMax; 

     

    if(NULL == ppTreeNode || NULL == *ppTreeNode) 

        return FALSE; 

     

    pTreeNode = find_data_in_tree_node(*ppTreeNode, data); 

    if(NULL == pTreeNode) 

        return FALSE; 

     

    if(*ppTreeNode == pTreeNode){ 

         

        if(NULL == pTreeNode->left_child && NULL == pTreeNode->right_child){ 

            *ppTreeNode = NULL; 

        }else if(NULL != pTreeNode->left_child && NULL == pTreeNode->right_child){ 

            *ppTreeNode = pTreeNode->left_child; 

            pTreeNode->left_child->parent = NULL; 

        }else if(NULL == pTreeNode->left_child && NULL != pTreeNode->right_child){ 

            *ppTreeNode = pTreeNode->right_child; 

            pTreeNode->right_child->parent = NULL; 

        }else{ 

            pLeftMax = find_max_node(pTreeNode->left_child); 

            if(pLeftMax == pTreeNode->left_child){ 

                *ppTreeNode = pTreeNode->left_child; 

                (*ppTreeNode)->right_child = pTreeNode->right_child; 

                (*ppTreeNode)->right_child->parent = *ppTreeNode; 

                (*ppTreeNode)->parent = NULL; 

            } 

        } 

         

        free(pTreeNode); 

        return TRUE; 

    } 

     

    return TRUE; 

STATUS delete_node_from_tree(TREE_NODE** ppTreeNode, int data)

{

       TREE_NODE* pTreeNode;

       TREE_NODE* pLeftMax;

      

       if(NULL == ppTreeNode || NULL == *ppTreeNode)

              return FALSE;

      

       pTreeNode = find_data_in_tree_node(*ppTreeNode, data);

       if(NULL == pTreeNode)

              return FALSE;

      

       if(*ppTreeNode == pTreeNode){

             

              if(NULL == pTreeNode->left_child && NULL == pTreeNode->right_child){

                     *ppTreeNode = NULL;

              }else if(NULL != pTreeNode->left_child && NULL == pTreeNode->right_child){

                     *ppTreeNode = pTreeNode->left_child;

                     pTreeNode->left_child->parent = NULL;

              }else if(NULL == pTreeNode->left_child && NULL != pTreeNode->right_child){

                     *ppTreeNode = pTreeNode->right_child;

                     pTreeNode->right_child->parent = NULL;

              }else{

                     pLeftMax = find_max_node(pTreeNode->left_child);

                     if(pLeftMax == pTreeNode->left_child){

                            *ppTreeNode = pTreeNode->left_child;

                            (*ppTreeNode)->right_child = pTreeNode->right_child;

                            (*ppTreeNode)->right_child->parent = *ppTreeNode;

                            (*ppTreeNode)->parent = NULL;

                     }

              }

             

              free(pTreeNode);

              return TRUE;

       }

      

       return TRUE;

}    上面的代碼中添加的內容表示了我們介紹的這一情形。為此,我們可以設計一種測試用例。依次插入10、6、5、15,然後刪除10即可。

 

 

static void test6() 

    TREE_NODE* pTreeNode = NULL; 

    assert(TRUE == insert_node_into_tree(&pTreeNode, 10)); 

    assert(TRUE == insert_node_into_tree(&pTreeNode, 6)); 

    assert(TRUE == insert_node_into_tree(&pTreeNode, 5)); 

    assert(TRUE == insert_node_into_tree(&pTreeNode, 15)); 

    assert(TRUE == delete_node_from_tree(&pTreeNode, 10)); 

    assert(6 == pTreeNode->data); 

    assert(NULL == pTreeNode->parent); 

    assert(15 == pTreeNode->right_child->data); 

    assert(pTreeNode = pTreeNode->right_child->parent); 

    assert(NULL == pTreeNode->parent); 

    free(pTreeNode->left_child); 

    free(pTreeNode->right_child); 

    free(pTreeNode); 

static void test6()

{

       TREE_NODE* pTreeNode = NULL;

       assert(TRUE == insert_node_into_tree(&pTreeNode, 10));

       assert(TRUE == insert_node_into_tree(&pTreeNode, 6));

       assert(TRUE == insert_node_into_tree(&pTreeNode, 5));

       assert(TRUE == insert_node_into_tree(&pTreeNode, 15));

       assert(TRUE == delete_node_from_tree(&pTreeNode, 10));

       assert(6 == pTreeNode->data);

       assert(NULL == pTreeNode->parent);

       assert(15 == pTreeNode->right_child->data);

       assert(pTreeNode = pTreeNode->right_child->parent);

       assert(NULL == pTreeNode->parent);

       free(pTreeNode->left_child);

       free(pTreeNode->right_child);

       free(pTreeNode);

}    如果上面的測試用例通過,表示我們添加的代碼沒有問題。

 

 

 

 

    2)左節點不是當前左子樹的最大節點,情形如下所示

 

 

/*

*               

*         10          ======>     8

*        /  \                   /   \

*      6     15               5     15

*       \                      

*        8                     

*/ 

/*

*              

*         10          ======>     8

*        /  \                   /   \

*      6     15               5     15

*       \                     

*        8                    

*/    此時,我們應該用10左側的最大節點8代替刪除的節點10即可。

 

 

STATUS delete_node_from_tree(TREE_NODE** ppTreeNode, int data) 

    TREE_NODE* pTreeNode; 

    TREE_NODE* pLeftMax; 

     

    if(NULL == ppTreeNode || NULL == *ppTreeNode) 

        return FALSE; 

     

    pTreeNode = find_data_in_tree_node(*ppTreeNode, data); 

    if(NULL == pTreeNode) 

        return FALSE; 

     

    if(*ppTreeNode == pTreeNode){ 

         

        if(NULL == pTreeNode->left_child && NULL == pTreeNode->right_child){ 

            *ppTreeNode = NULL; 

        }else if(NULL != pTreeNode->left_child && NULL == pTreeNode->right_child){ 

            *ppTreeNode = pTreeNode->left_child; 

            pTreeNode->left_child->parent = NULL; 

        }else if(NULL == pTreeNode->left_child && NULL != pTreeNode->right_child){ 

            *ppTreeNode = pTreeNode->right_child; 

            pTreeNode->right_child->parent = NULL; 

        }else{ 

            pLeftMax = find_max_node(pTreeNode->left_child); 

            if(pLeftMax == pTreeNode->left_child){ 

                *ppTreeNode = pTreeNode->left_child; 

                (*ppTreeNode)->right_child = pTreeNode->right_child; 

                (*ppTreeNode)->right_child->parent = *ppTreeNode; 

                (*ppTreeNode)->parent = NULL; 

            }else{ 

                pTreeNode->data = pLeftMax->data; 

                pLeftMax->parent->right_child = NULL; 

                pTreeNode = pLeftMax; 

            } 

        } 

         

        free(pTreeNode); 

        return TRUE; 

    } 

     

    return TRUE; 

STATUS delete_node_from_tree(TREE_NODE** ppTreeNode, int data)

{

       TREE_NODE* pTreeNode;

       TREE_NODE* pLeftMax;

      

       if(NULL == ppTreeNode || NULL == *ppTreeNode)

              return FALSE;

      

       pTreeNode = find_data_in_tree_node(*ppTreeNode, data);

       if(NULL == pTreeNode)

              return FALSE;

      

       if(*ppTreeNode == pTreeNode){

             

              if(NULL == pTreeNode->left_child && NULL == pTreeNode->right_child){

                     *ppTreeNode = NULL;

              }else if(NULL != pTreeNode->left_child && NULL == pTreeNode->right_child){

                     *ppTreeNode = pTreeNode->left_child;

                     pTreeNode->left_child->parent = NULL;

              }else if(NULL == pTreeNode->left_child && NULL != pTreeNode->right_child){

                     *ppTreeNode = pTreeNode->right_child;

                     pTreeNode->right_child->parent = NULL;

              }else{

                     pLeftMax = find_max_node(pTreeNode->left_child);

                     if(pLeftMax == pTreeNode->left_child){

                            *ppTreeNode = pTreeNode->left_child;

                            (*ppTreeNode)->right_child = pTreeNode->right_child;

                            (*ppTreeNode)->right_child->parent = *ppTreeNode;

                            (*ppTreeNode)->parent = NULL;

                     }else{

                            pTreeNode->data = pLeftMax->data;

                            pLeftMax->parent->right_child = NULL;

                            pTreeNode = pLeftMax;

                     }

              }

             

              free(pTreeNode);

              return TRUE;

       }

      

       return TRUE;

}    那麼,這個場景下面測試用例又該怎麼設計呢?其實只需要按照上面給出的示意圖進行即可。依次插入數據10、6、8、15,然後刪除數據10。

 

 

static void test7() 

    TREE_NODE* pTreeNode = NULL; 

    assert(TRUE == insert_node_into_tree(&pTreeNode, 10)); 

    assert(TRUE == insert_node_into_tree(&pTreeNode, 6)); 

    assert(TRUE == insert_node_into_tree(&pTreeNode, 8)); 

    assert(TRUE == insert_node_into_tree(&pTreeNode, 15)); 

    assert(TRUE == delete_node_from_tree(&pTreeNode, 10)); 

    assert(8 == pTreeNode->data); 

    assert(NULL == pTreeNode->parent); 

    assert(NULL == pTreeNode->left_child->right_child); 

    assert(NULL == pTreeNode->parent); 

    free(pTreeNode->left_child); 

    free(pTreeNode->right_child); 

    free(pTreeNode); 

static void test7()

{

       TREE_NODE* pTreeNode = NULL;

       assert(TRUE == insert_node_into_tree(&pTreeNode, 10));

       assert(TRUE == insert_node_into_tree(&pTreeNode, 6));

       assert(TRUE == insert_node_into_tree(&pTreeNode, 8));

       assert(TRUE == insert_node_into_tree(&pTreeNode, 15));

       assert(TRUE == delete_node_from_tree(&pTreeNode, 10));

       assert(8 == pTreeNode->data);

       assert(NULL == pTreeNode->parent);

       assert(NULL == pTreeNode->left_child->right_child);

       assert(NULL == pTreeNode->parent);

       free(pTreeNode->left_child);

       free(pTreeNode->right_child);

       free(pTreeNode);

}    至此,刪除節點為根節點的情形全部討論完畢,那麼如果刪除的節點是普通節點呢,那應該怎麼解決呢?

 

 

STATUS delete_node_from_tree(TREE_NODE** ppTreeNode, int data) 

    TREE_NODE* pTreeNode; 

    TREE_NODE* pLeftMax; 

     

    if(NULL == ppTreeNode || NULL == *ppTreeNode) 

        return FALSE; 

     

    pTreeNode = find_data_in_tree_node(*ppTreeNode, data); 

    if(NULL == pTreeNode) 

        return FALSE; 

     

    if(*ppTreeNode == pTreeNode){ 

         

        if(NULL == pTreeNode->left_child && NULL == pTreeNode->right_child){ 

            *ppTreeNode = NULL; 

        }else if(NULL != pTreeNode->left_child && NULL == pTreeNode->right_child){ 

            *ppTreeNode = pTreeNode->left_child; 

            pTreeNode->left_child->parent = NULL; 

        }else if(NULL == pTreeNode->left_child && NULL != pTreeNode->right_child){ 

            *ppTreeNode = pTreeNode->right_child; 

            pTreeNode->right_child->parent = NULL; 

        }else{ 

            pLeftMax = find_max_node(pTreeNode->left_child); 

            if(pLeftMax == pTreeNode->left_child){ 

                *ppTreeNode = pTreeNode->left_child; 

                (*ppTreeNode)->right_child = pTreeNode->right_child; 

                (*ppTreeNode)->right_child->parent = *ppTreeNode; 

                (*ppTreeNode)->parent = NULL; 

            }else{ 

                pTreeNode->data = pLeftMax->data; 

                pLeftMax->parent->right_child = NULL; 

                pTreeNode = pLeftMax; 

            } 

        } 

         

        free(pTreeNode); 

        return TRUE; 

    } 

     

    return _delete_node_from_tree(pTreeNode); 

STATUS delete_node_from_tree(TREE_NODE** ppTreeNode, int data)

{

       TREE_NODE* pTreeNode;

       TREE_NODE* pLeftMax;

      

       if(NULL == ppTreeNode || NULL == *ppTreeNode)

              return FALSE;

      

       pTreeNode = find_data_in_tree_node(*ppTreeNode, data);

       if(NULL == pTreeNode)

              return FALSE;

      

       if(*ppTreeNode == pTreeNode){

             

              if(NULL == pTreeNode->left_child && NULL == pTreeNode->right_child){

                     *ppTreeNode = NULL;

              }else if(NULL != pTreeNode->left_child && NULL == pTreeNode->right_child){

                     *ppTreeNode = pTreeNode->left_child;

                     pTreeNode->left_child->parent = NULL;

              }else if(NULL == pTreeNode->left_child && NULL != pTreeNode->right_child){

                     *ppTreeNode = pTreeNode->right_child;

                     pTreeNode->right_child->parent = NULL;

              }else{

                     pLeftMax = find_max_node(pTreeNode->left_child);

                     if(pLeftMax == pTreeNode->left_child){

                            *ppTreeNode = pTreeNode->left_child;

                            (*ppTreeNode)->right_child = pTreeNode->right_child;

                            (*ppTreeNode)->right_child->parent = *ppTreeNode;

                            (*ppTreeNode)->parent = NULL;

                     }else{

                            pTreeNode->data = pLeftMax->data;

                            pLeftMax->parent->right_child = NULL;

                            pTreeNode = pLeftMax;

                     }

              }

             

              free(pTreeNode);

              return TRUE;

       }

      

       return _delete_node_from_tree(pTreeNode);

}    我們在當前函數的最後一行添加_delete_node_from_tree,這個函數用來處理普通節點的刪除情況,我們會在下面一篇博客中繼續介紹。

 

 

 

 

    3、 普通節點的刪除

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved