2.4 The left and right subtree of the deleted node exists, which is divided into two situations.
1) The left node is the largest node of the current left subtree. You only need to replace the root node with the left node.
/** * 10 ======> 6* / \ / \* 6 15 5 15* / * 5 */
How can I write the code?
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;}
The content added in the above Code indicates the situation we introduced. Therefore, we can design a test case. Insert 10, 6, 5, and 15 in sequence, and then delete 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);}
If the preceding test case passes, the code we added is correct.
2) The left node is not the largest node of the current left subtree, as shown below:
/** * 10 ======> 8* / \ / \* 6 15 5 15* \ * 8 */
In this case, we should replace the deleted node 10 with the maximum node 8 on the left.
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;}
How can we design the test cases in this scenario? In fact, you only need to follow the above steps. Insert data 10, 6, 8, and 15 in sequence, and then delete data 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);}
So far, all the cases of deleting a node as the root node have been discussed. If the deleted node is a common node, how can this problem be solved?
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);}
We add _ delete_node_from_tree to the last row of the current function. This function is used to delete common nodes. We will continue to introduce it in the following blog.
3. Delete common nodes
(To be continued)