3 普通節點的刪除
3.1 刪除的節點沒有左子樹,也沒有右子樹
測試案例1: 刪除節點6
/** * 10 ======> 10* / \ \* 6 15 15* */static void test8(){TREE_NODE* pTreeNode = NULL;assert(TRUE == insert_node_into_tree(&pTreeNode, 10));assert(TRUE == insert_node_into_tree(&pTreeNode, 6));assert(6 == pTreeNode->left_child->data);assert(TRUE == insert_node_into_tree(&pTreeNode, 15));assert(TRUE == delete_node_from_tree(&pTreeNode, 6));assert(NULL == pTreeNode->left_child);free(pTreeNode->right_child);free(pTreeNode);}
測試案例2: 刪除節點15
/** * 10 ======> 10* / \ / * 6 15 6 * */static void test9(){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, 15));assert(15 == pTreeNode->right_child->data);assert(TRUE == delete_node_from_tree(&pTreeNode, 15));assert(NULL == pTreeNode->right_child);free(pTreeNode->right_child);free(pTreeNode);}
那麼代碼應該怎麼編寫呢?
STATUS _delete_node_from_tree(TREE_NODE* pTreeNode){TREE_NODE* pLeftMax;if(NULL == pTreeNode-> left_child && NULL == pTreeNode->right_child){if(pTreeNode == pTreeNode->parent->left_child)pTreeNode->parent->left_child = NULL;elsepTreeNode->parent->right_child = NULL;}free(pTreeNode);return TRUE;}
3.2 刪除的節點有左子樹,沒有右子樹
測試案例1: 測試節點6
/** * 10 ======> 10* / / * 6 3 * /* 3 */static void test10(){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, 3));assert(TRUE == delete_node_from_tree(&pTreeNode, 6));assert(3 == pTreeNode->left_child->data);assert(pTreeNode = pTreeNode->left_child->parent);free(pTreeNode->left_child);free(pTreeNode);}
測試案例2: 刪除節點15
/** * 10 ======> 10* \ \* 15 12* / * 12 */static void test11(){TREE_NODE* pTreeNode = NULL;assert(TRUE == insert_node_into_tree(&pTreeNode, 10));assert(TRUE == insert_node_into_tree(&pTreeNode, 15));assert(TRUE == insert_node_into_tree(&pTreeNode, 12));assert(TRUE == delete_node_from_tree(&pTreeNode, 15));assert(12 == pTreeNode->right_child->data);assert(pTreeNode = pTreeNode->right_child->parent);free(pTreeNode->right_child);free(pTreeNode);}
添加左子樹不為空白,右子樹為空白的處理代碼,如下所示:
STATUS _delete_node_from_tree(TREE_NODE* pTreeNode){TREE_NODE* pLeftMax;if(NULL == pTreeNode-> left_child && NULL == pTreeNode->right_child){if(pTreeNode == pTreeNode->parent->left_child)pTreeNode->parent->left_child = NULL;elsepTreeNode->parent->right_child = NULL;}else if(NULL != pTreeNode->left_child && NULL == pTreeNode->right_child){pTreeNode->left_child->parent = pTreeNode->parent;if(pTreeNode == pTreeNode->parent->left_child)pTreeNode->parent->left_child = pTreeNode->left_child;elsepTreeNode->parent->right_child = pTreeNode->left_child;}free(pTreeNode);return TRUE;}
3.3 刪除的節點左子樹為空白,右子樹節點不為空白
測試案例1: 刪除資料6
/** * 10 ======> 10* / / * 6 8 * \* 8 */static void test12(){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 == delete_node_from_tree(&pTreeNode, 6));assert(8 == pTreeNode->left_child->data);assert(pTreeNode = pTreeNode->left_child->parent);free(pTreeNode->left_child);free(pTreeNode);}
測試案例2: 刪除資料15
/** * 10 ======> 10* \ \ * 15 20 * \* 20 */static void test13(){TREE_NODE* pTreeNode = NULL;assert(TRUE == insert_node_into_tree(&pTreeNode, 10));assert(TRUE == insert_node_into_tree(&pTreeNode, 15));assert(TRUE == insert_node_into_tree(&pTreeNode, 20));assert(TRUE == delete_node_from_tree(&pTreeNode, 15));assert(20 == pTreeNode->right_child->data);assert(pTreeNode = pTreeNode->right_child->parent);free(pTreeNode->right_child);free(pTreeNode);}
添加左子樹為空白,右子樹不為空白的處理情形。代碼如下:
STATUS _delete_node_from_tree(TREE_NODE* pTreeNode){TREE_NODE* pLeftMax;if(NULL == pTreeNode-> left_child && NULL == pTreeNode->right_child){if(pTreeNode == pTreeNode->parent->left_child)pTreeNode->parent->left_child = NULL;elsepTreeNode->parent->right_child = NULL;}else if(NULL != pTreeNode->left_child && NULL == pTreeNode->right_child){pTreeNode->left_child->parent = pTreeNode->parent;if(pTreeNode == pTreeNode->parent->left_child)pTreeNode->parent->left_child = pTreeNode->left_child;elsepTreeNode->parent->right_child = pTreeNode->left_child;}else if(NULL == pTreeNode->left_child && NULL != pTreeNode->right_child){pTreeNode->right_child->parent = pTreeNode->parent;if(pTreeNode == pTreeNode->parent->left_child)pTreeNode->parent->left_child = pTreeNode->right_child;elsepTreeNode->parent->right_child = pTreeNode->right_child;}free(pTreeNode);return TRUE;}
3.4 刪除的節點左右子樹均不為空白,不過又要分為兩種情形:
1) 左節點是刪除節點左側的最大節點 (刪除節點6)
/** * 10 ======> 10* / / * 6 5 * / \ \* 5 8 8 */static void test14(){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, 8));assert(TRUE == delete_node_from_tree(&pTreeNode, 6));assert(5 == pTreeNode->left_child->data);assert(pTreeNode = pTreeNode->left_child->parent);assert( 8 == pTreeNode->left_child->right_child->data);assert(pTreeNode->left_child = pTreeNode->left_child->right_child->parent);free(pTreeNode->left_child->right_child);free(pTreeNode->left_child);free(pTreeNode);}
2) 左節點不是刪除節點左側的最大節點(刪除節點5)
/** * 10 ======> 10* / / * 5 4 * / \ / \* 2 6 2 6* \ * 4*/static void test15(){TREE_NODE* pTreeNode = NULL;assert(TRUE == insert_node_into_tree(&pTreeNode, 10));assert(TRUE == insert_node_into_tree(&pTreeNode, 5));assert(TRUE == insert_node_into_tree(&pTreeNode, 2));assert(TRUE == insert_node_into_tree(&pTreeNode, 4));assert(TRUE == insert_node_into_tree(&pTreeNode, 6));assert(TRUE == delete_node_from_tree(&pTreeNode, 5));assert(4 == pTreeNode->left_child->data);assert(NULL == pTreeNode->left_child->left_child->right_child);free(pTreeNode->left_child->left_child);free(pTreeNode->left_child->right_child);free(pTreeNode->left_child);free(pTreeNode);}
那麼針對這兩種類型,我們的代碼究竟應該怎麼處理呢?
STATUS _delete_node_from_tree(TREE_NODE* pTreeNode){TREE_NODE* pLeftMax;if(NULL == pTreeNode-> left_child && NULL == pTreeNode->right_child){if(pTreeNode == pTreeNode->parent->left_child)pTreeNode->parent->left_child = NULL;elsepTreeNode->parent->right_child = NULL;}else if(NULL != pTreeNode->left_child && NULL == pTreeNode->right_child){pTreeNode->left_child->parent = pTreeNode->parent;if(pTreeNode == pTreeNode->parent->left_child)pTreeNode->parent->left_child = pTreeNode->left_child;elsepTreeNode->parent->right_child = pTreeNode->left_child;}else if(NULL == pTreeNode->left_child && NULL != pTreeNode->right_child){pTreeNode->right_child->parent = pTreeNode->parent;if(pTreeNode == pTreeNode->parent->left_child)pTreeNode->parent->left_child = pTreeNode->right_child;elsepTreeNode->parent->right_child = pTreeNode->right_child;}else{pLeftMax = find_max_node(pTreeNode->left_child);if(pLeftMax == pTreeNode->left_child){if(pTreeNode == pTreeNode->parent->left_child)pTreeNode->parent->left_child = pTreeNode->left_child;elsepTreeNode->parent->right_child = pTreeNode->left_child;pTreeNode->left_child->parent = pTreeNode->parent;pTreeNode->left_child->right_child = pTreeNode->right_child;pTreeNode->right_child->parent = pTreeNode-> left_child;}else{pTreeNode->data = pLeftMax->data;pLeftMax->parent->right_child = pLeftMax->left_child;pTreeNode = pLeftMax;}}free(pTreeNode);return TRUE;}
結束總結:
上面的過程記錄了我們的代碼是怎麼一步一步走過來的。最後我們給出一份完整的節點刪除代碼:
STATUS _delete_node_from_tree(TREE_NODE* pTreeNode){TREE_NODE* pLeftMax;if(NULL == pTreeNode-> left_child && NULL == pTreeNode->right_child){if(pTreeNode == pTreeNode->parent->left_child)pTreeNode->parent->left_child = NULL;elsepTreeNode->parent->right_child = NULL;}else if(NULL != pTreeNode->left_child && NULL == pTreeNode->right_child){pTreeNode->left_child->parent = pTreeNode->parent;if(pTreeNode == pTreeNode->parent->left_child)pTreeNode->parent->left_child = pTreeNode->left_child;elsepTreeNode->parent->right_child = pTreeNode->left_child;}else if(NULL == pTreeNode->left_child && NULL != pTreeNode->right_child){pTreeNode->right_child->parent = pTreeNode->parent;if(pTreeNode == pTreeNode->parent->left_child)pTreeNode->parent->left_child = pTreeNode->right_child;elsepTreeNode->parent->right_child = pTreeNode->right_child;}else{pLeftMax = find_max_node(pTreeNode->left_child);if(pLeftMax == pTreeNode->left_child){if(pTreeNode == pTreeNode->parent->left_child)pTreeNode->parent->left_child = pTreeNode->left_child;elsepTreeNode->parent->right_child = pTreeNode->left_child;pTreeNode->left_child->parent = pTreeNode->parent;pTreeNode->left_child->right_child = pTreeNode->right_child;pTreeNode->right_child->parent = pTreeNode-> left_child;}else{pTreeNode->data = pLeftMax->data;pLeftMax->parent->right_child = pLeftMax->left_child;pTreeNode = pLeftMax;}}free(pTreeNode);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 = pLeftMax->left_child;pTreeNode = pLeftMax;}}free(pTreeNode);return TRUE;}return _delete_node_from_tree(pTreeNode);}