我正在测试从二进制搜索树中删除节点的功能,但是发现我无法删除叶节点。当涉及到打印整棵树时,Visual Studio在in_order函数中给了我这个错误。 -引发异常:读取访问冲突。 树是0xDDDDDDDD。
想知道如何解决它,因为到目前为止它在所有其他情况下都有效。
void in_order(BinTreeNode* tree) {
if (tree->left != NULL)
in_order(tree->left);
std::cout << tree->value << std::endl;
if (tree->right != NULL)
in_order(tree->right);
}
void deleteNodeFromBST(BinTreeNode* root_value, int key_value)
{
BinTreeNode* selected_node = root_value;
BinTreeNode* previous_selected_node = NULL;
bool foundNode = false;
/* find the node we want to delete */
while (foundNode == false)
{
if (selected_node == NULL)
{
return;
}
else
{
if (selected_node->value == key_value)
{
foundNode = true;
}
else
{
previous_selected_node = selected_node;
if (key_value > selected_node->value)
selected_node = selected_node->right;
else
selected_node = selected_node->left;
}
}
}
if (foundNode == false)
{
return;
}
/* if the node has no children, just delete it */
if (selected_node->left == NULL && selected_node->right == NULL)
{
if (previous_selected_node->left == selected_node)
previous_selected_node->left == NULL;
else
previous_selected_node->right = NULL;
delete selected_node;
return;
}
/* if the node has one child to the left , we replace the node with the child*/
else if (selected_node->left != NULL && selected_node->right == NULL)
{
if (previous_selected_node->left == selected_node)
{
previous_selected_node->left = selected_node->left;
delete selected_node;
selected_node = NULL;
return;
}
else
{
previous_selected_node->right = selected_node->left;
delete selected_node;
selected_node = NULL;
return;
}
}
/* if the node has one child to the right, we replace the node with the child*/
else if (selected_node->right != NULL && selected_node->left == NULL)
{
if (previous_selected_node->right == selected_node)
{
previous_selected_node->right = selected_node->right;
delete selected_node;
selected_node = NULL;
return;
}
else
{
previous_selected_node->left = selected_node->right;
delete selected_node;
selected_node = NULL;
return;
}
}
/*if the node we want to delete has two children, we find the max value in the left subtree and we replace it */
else if (selected_node->left != NULL && selected_node->right != NULL)
{
BinTreeNode* maxLeftValue = selected_node->left;
BinTreeNode* maxLeftValuePrev = selected_node;
while (maxLeftValue->right != NULL)
{
maxLeftValuePrev = maxLeftValue;
maxLeftValue = maxLeftValue->right;
}
selected_node->value = maxLeftValue->value;
if (maxLeftValue->left != NULL)
{
maxLeftValuePrev->right = maxLeftValue->left;
}
else
{
maxLeftValuePrev = NULL;
}
delete maxLeftValue;
maxLeftValue = NULL;
return;
}
}
int main(int argc, char *argv[])
{
//BinTreeNode* t = tree_insert(0, 6);
/*tree_insert(t, 10);
tree_insert(t, 5);
tree_insert(t, 2);
tree_insert(t, 3);
tree_insert(t, 4);
tree_insert(t, 11);*/
BinTreeNode* t = tree_insert(0, 20);
tree_insert(t, 15);
tree_insert(t, 19);
tree_insert(t, 11);
tree_insert(t, 13);
tree_insert(t, 9);
tree_insert(t, 12);
tree_insert(t, 5);
tree_insert(t, 2);
tree_insert(t, 3);
deleteNodeFromBST(t, 16);
deleteNodeFromBST(t, 19);
deleteNodeFromBST(t, 13);
deleteNodeFromBST(t, 11);
in_order(t);
return 0;
}
答案 0 :(得分:0)
更改函数的最后几行:
void deleteNodeFromBST(BinTreeNode* root_value, int key_value)
{
.
.
.
else if (selected_node->left != NULL && selected_node->right != NULL)
{
.
.
.
if(maxLeftValuePrev->left == maxLeftValue)
maxLeftValuePrev->left = maxLeftValue->left;
else
maxLeftValuePrev->right = maxLeftValue->left;
delete maxLeftValue;
maxLeftValue = NULL;
return;
}
}
代码中的逻辑是:
如果要删除的节点有两个子节点,则在左侧子树(子树的最右节点)中找到最大值,然后替换它,然后删除子树的该最右节点-“ maxLeftValue
” 。您应该将maxLeftValuePrev-right
设置为NULL,而不是maxLeftValuePrev
答案 1 :(得分:0)
此代码:
if (maxLeftValue->left != NULL)
{
maxLeftValuePrev->right = maxLeftValue->left;
}
else
{
maxLeftValuePrev = NULL;
}
包含两个错误。首先,正如@DrakeWu指出的,第二个分配是错误的;它将一个新值分配给一个局部变量,该变量将不再使用,并且可以在树上留下指向已删除节点的指针。其次,第一个赋值假定maxLeftValue
是右子节点。如果(可能发生)它是左子节点,则一个节点可以成为两个不同节点的子节点,这样树不再是一棵树。
这是更正此代码的一种方法:
if(maxLeftValuePrev->left == maxLeftValue)
maxLeftValuePrev->left = maxLeftValue->left;
else
maxLeftValuePrev->right = maxLeftValue->left;
(而且,您的命名约定不好-您不应该给 node 一个以“ Value” 结尾的名称。)