我在BST中移除节点时遇到问题,当节点同时有两个子节点是我的删除代码时:
void remove(int val)
{
treeNode *ptr=root,*prev=root;
if(root->data==val)
{
if(root->left==NULL &&root->right==NULL)
root=NULL;
else if(root->left==NULL)
{
root=root->right;
delete ptr;
}
else if(root->right==NULL)
{
root=root->left;
delete ptr;
}
else
{
swap(root,root->left);
delete root->left;
root->left=NULL;
}
return;
}
else
{
while(ptr->data!=val)
{
prev=ptr;
if(val<ptr->data)
ptr=ptr->left;
else if(val>ptr->data)
ptr=ptr->right;
}
if(ptr->left==NULL && ptr->right==NULL)
{
if(prev->left==ptr)
prev->left=NULL;
else if(prev->right==ptr)
prev->right=NULL;
delete ptr;
ptr=NULL;
}
else if(ptr->left==NULL)
{
root=root->right;
delete ptr;
}
else if(ptr->right==NULL)
{
root=root->left;
delete ptr;
}
else
{
swap(ptr,ptr->left);
delete ptr->left;
ptr->left=NULL;
}
}
}
某些测试用例已成功通过,例如:
3
3 4 5
1
d 3
和
5
21 16 78 1 22
2
i 20 d 16
但是这样的输入会使程序终止
3
3 2 1
1
d 2
可以查看完整代码here。
答案 0 :(得分:1)
您的问题在于remove-method的“else”分支中的以下几行:
else if(ptr->left==NULL)
{
root=root->right;
delete ptr;
}
else if(ptr->right==NULL)
{
root=root->left;
delete ptr;
}
可能你忘了在复制和粘贴第一个案例后实现这些。快速入侵让我想到了这个:
// the node we found has only a single child
else if(ptr->left==NULL || ptr->right==NULL)
{
// we need to re-add the non-empty sub-tree
treeNode *partialTree = (ptr->left == NULL) ? ptr->right : ptr->left;
// add the sub-tree on the place where ptr was linked
if (prev->left == ptr)
prev->left = partialTree;
else
prev->right = partialTree;
delete ptr;
}
答案 1 :(得分:0)
您的remove
功能错误。在原始代码中,您始终修改root
而不是ptr
的子指针。如果一个节点有2个孩子你就不会推广继任者。阅读有关删除有两个孩子的BST节点的信息。
此外,我创建了一个sentinal节点,这样您就不必检查在根节点发生的删除。使用此构造函数
#include<limits.h>
binarySearchTree()
{
root=new treeNode;
root->data=INT_MAX;
root->right=NULL;
root->left=NULL;
}
void remove(int val)
{
treeNode *ptr=root,*prev=root;
while(ptr->data!=val)
{
prev=ptr;
if(val<ptr->data)
ptr=ptr->left;
else if(val>ptr->data)
ptr=ptr->right;
}
if(ptr->left==NULL && ptr->right==NULL)
{
if(prev->left==ptr)
prev->left=NULL;
else if(prev->right==ptr)
prev->right=NULL;
delete ptr;
ptr=NULL;
}
else if(ptr->left==NULL)
{
if(prev->left==ptr)
{
prev->left = ptr->right;
}
else
{
prev->right = ptr->right;
}
delete ptr;
}
else if(ptr->right==NULL)
{
if(prev->left==ptr)
{
prev->left = ptr->left;
}
else
{
prev->right = ptr->left;
}
delete ptr;
}
else //two children. Get the right Child's leftmost node (say X) and set ptr->data := X->data. Then delete X
{
treeNode* rChild = ptr->right;
treeNode* rChildParent = ptr;
while(rChild->left != NULL)
{
rChildParent=rChild;
rChild = rChild->left;
}
ptr->data=rChild->data;
if(rChildParent == ptr)
{
ptr->right=rChild->right;
}
else
{
rChildParent->left=rChild->right;
}
delete rChild;
}
}