【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】
2.4 删除节点的左右子树都存在,此时又会分成两种情形
1)左节点是当前左子树的最大节点,此时只需要用左节点代替根节点即可
/*
*
* 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;
}
上面的代码中添加的内容表示了我们介绍的这一情形。为此,我们可以设计一种测试用例。依次插入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);
}
如果上面的测试用例通过,表示我们添加的代码没有问题。
2)左节点不是当前左子树的最大节点,情形如下所示
/*
*
* 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;
}
那么,这个场景下面测试用例又该怎么设计呢?其实只需要按照上面给出的示意图进行即可。依次插入数据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);
}
至此,删除节点为根节点的情形全部讨论完毕,那么如果删除的节点是普通节点呢,那应该怎么解决呢?
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;
pLeftMax->left_child->parent = pLeftMax->parent;
pTreeNode = pLeftMax;
}
}
free(pTreeNode);
return TRUE;
}
return _delete_node_from_tree(pTreeNode);
}
我们在当前函数的最后一行添加_delete_node_from_tree,这个函数用来处理普通节点的删除情况,我们会在下面一篇博客中继续介绍。
3、 普通节点的删除
(待续)
分享到:
相关推荐
二维矩形装箱算法--二叉树--java实现.rar
多个车子,N个箱子,用二维矩形方式进行装车。采用二叉树实现。java
2------前序遍历递归算法 3------前序遍历非递归算法 4------中序遍历递归算法 5------中序遍历非递归算法 6------后序遍历递归算法 7------后序遍历非递归算法 8------求树高 9------求叶子总数 10-----输出二叉树 ...
算法大全-面试题-链表-栈-二叉树-数据结构
二叉树排序二叉树排序二叉树排序二叉树排序二叉树排序二叉树排序二叉树排序
数据结构--二叉树--思维导图.pdf
包含排序,链表,图,队列,二叉树算法c++实现,这些c++是自己写的都能运行,另外还有一些c的算法实现
二叉树实现-完美版-二叉树操作-整个实现用C++实现
二叉树二叉树二叉树二叉树二叉树二叉树二叉树二叉树二叉树二叉树二叉树二叉树二叉树二叉树二叉树
算法大全-面试题-链表-栈-二叉树-数据结构.docx 一、单链表 目录 1.单链表反转 2.找出单链表的倒数第4个元素 3.找出单链表的中间元素 4.删除无头单链表的一个节点 5.两个不交叉的有序链表的合并 6.有个二级...
java 常见排序算法的实现 有冒泡、选择、快速、比较等常见的排序算法 还包括二叉树的实现
算法-树形结构- 树与二叉树- 树的数据生成器.rar
算法分类:排序算法(如冒泡排序、快速排序、归并排序),查找算法(如顺序查找、二分查找、哈希查找),图论算法(如Dijkstra最短路径算法、Floyd-Warshall算法、Prim最小生成树算法),动态规划,贪心算法,回溯法...
算法-树形结构- 树与二叉树- 树的中心.rar
算法-树形结构- 树与二叉树- 树的直径.rar
算法-树形结构- 树与二叉树- 树的重心.rar