从BST删除节点时出错

Error when Deleting Node from BST

本文关键字:出错 节点 删除 BST      更新时间:2023-10-16

这确实让我感到困惑。我有一个由城市名称订购的城市二元搜索树。一个城市还包含人口和GPS坐标。我希望能够通过城市名称或城市坐标从树上删除节点。我的名称可以删除正常工作,但是GPS坐标不起作用。

当我尝试打印二进制树时,当我通过GPS删除节点时,我会得到堆栈跨流。以下是我的一些代码。我不明白,如果我按名称删除它,它将如何工作,但是如果我使用相同的删除方法,则不能按坐标删除。

我遇到的确切错误是" exe中的0x013214d6 inthanded Exception:0xc00000fd:stack Overflow(参数:0x00000001,0x00152ffc(。"这是在我通过坐标删除后的打印功能中发生的,但如果我以名称删除。

bool BinaryTree::DeleteByName(string city)
{
    if (GetRoot() != NULL)
    {
        return (DeleteByName(GetRoot(), city));
    }
    return false;
}
TreeNode* BinaryTree::DeleteByName(TreeNode *node, string city)
{
    if (node == NULL)
    {
        return node;
    }
    else if (city < node->Data.name)
    {
        node->Left = DeleteByName(node->Left, city);
    }
    else if (city > node->Data.name)
    {
        node->Right = DeleteByName(node->Right, city);
    }
    else
    {
        if (node->Left == NULL && node->Right == NULL)
        {
            delete node;
            node = NULL;
        }
        else if (node->Left == NULL)        
        {
            TreeNode* temp = node;
            node = node->Right;
            delete temp;
        }
        else if (node->Right == NULL)
        {
            TreeNode* temp = node;
            node = node->Left;
            delete temp;
        }
        else
        {
            cout << "Else";
            TreeNode* temp = MinPtr(node->Right);
            node->Data = temp->Data;
            node->Right = DeleteByName(node->Right, temp->Data.name);
        }
    }
    return node;
}
bool BinaryTree::DeleteByCoord(pair<double, double> coords)
{
    if (GetRoot() == NULL)
    {
        return false;
    }
    else
    {
        return DeleteByCoord(GetRoot(), coords);
    }
}
bool BinaryTree::DeleteByCoord(TreeNode* node, pair<double, double> coords)
{
    bool result;
    if (node == NULL)
    {
        return false;
    }
    else
    {
        if (node->Data.coordinates.first == coords.first && node->Data.coordinates.second == coords.second)
        {
            return (DeleteByName(node, node->Data.name));           
        }
        result = DeleteByCoord(node->Left, coords);
        if (result == true)
        {
            return result;
        }
        return DeleteByCoord(node->Right, coords);
    }
}


void BinaryTree::Insert(City city)
{
    TreeNode* temp = new TreeNode(city);
    if (GetRoot() == NULL)
    {
        root = temp;
    }
    else
    {
        Insert(temp, GetRoot());
    }
}
void BinaryTree::Insert(TreeNode* toAdd, TreeNode* addHere)
{
    if (toAdd->Data < addHere->Data)
    {
        if (addHere->Left != NULL)
        {
            Insert(toAdd, addHere->Left); 
        }
        else
        {
            addHere->Left = toAdd;
        }
    }
    else if (toAdd->Data > addHere->Data)
    {
        if (addHere->Right != NULL)
        {
            Insert(toAdd, addHere->Right);
        }
        else
        {
            addHere->Right = toAdd;
        }
    }
}
void BinaryTree::InOrderTraversal(TreeNode* node)
{
    if (node != NULL)
    {
        InOrderTraversal(node->Left);
        cout << node->Data << endl;
        InOrderTraversal(node->Right);
    }
}
void BinaryTree::InOrderTraversal()
{
    InOrderTraversal(GetRoot());
}
TreeNode* BinaryTree::GetRoot()
{
    return root;
}
TreeNode* BinaryTree::MinPtr(TreeNode* node)
{
    while (node->Left != NULL)
    {
        node = node->Left;
    }   
    return node;
}

删除节点时,还需要更新指向删除节点的父指针。在这里注意:

直接调用DeleteByName时,它会搜索所需的节点并返回NULL指针,该指针将自动设置为父节点指针:

else if (city < node->Data.name)
{
    node->Left = DeleteByName(node->Left, city);
}
else if (city > node->Data.name)
{
    node->Right = DeleteByName(node->Right, city);
}

但是,当您从坐标方法调用DeleteByName时,您不会重置父母的Left/Right指示:

if (node->Data.coordinates.first == coords.first && node->Data.coordinates.second == coords.second)
{
    return (DeleteByName(node, node->Data.name));           
}

DeleteByName已经收到所需的节点时,它不执行递归调用,也不会重置父母的指针:

else
{
    if (node->Left == NULL && node->Right == NULL)
    {
        delete node;
        node = NULL;
    }
    //... same here
}

注意:您的代码中还有更多问题。有些引起人们的注意:

  • DeleteByName返回指针,但是DeleteByCoord返回bool,您将指针用作DeleteByCoord中的布尔类型
  • 避免直接比较双打,比较结果可能是错误的。有关详细信息,请参见问题和解释。