3. Delete common nodes
3.1 No left or right subtree exists for the deleted Node
Test Case 1: delete node 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);}
Test Case 2: delete node 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);}
How should I write the code?
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 The deleted node has a left subtree and no right subtree.
Test Case 1: Test node 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);}
Test Case 2: delete node 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);}
The processing code for adding left subtree not empty but right subtree is empty is as follows:
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 The left subtree of the deleted node is empty, and the right subtree node is not empty.
Test Case 1: delete data 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);}
Test Case 2: delete data 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);}
Add a processing condition where the left subtree is empty and the right subtree is not empty. The Code is as follows:
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 The left and right subtree of the deleted node is not empty, but there are two scenarios:
1) The left node is the maximum node on the left of the node (delete node 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) The left node is not the largest node on the left of the node to be deleted (delete node 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);}
So what should we do with these two types of code?
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;}
Conclusion:
The above process records how our code came along step by step. Finally, we provide a complete Node Deletion code:
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);}