C++ 在二进制搜索树功能中使用指向指针的指针时出错

C++ 在二进制搜索树功能中使用指向指针的指针时出错,c++,pointers,pointer-to-pointer,C++,Pointers,Pointer To Pointer,我有以下代码: #include <iostream> #include <vector> #include <cstdlib> #include <ctime> using namespace std; struct Node { int value; Node *left, *right; Node(int value, Node *l = NULL, Node *r = NULL) { this

我有以下代码:

#include <iostream>
#include <vector>
#include <cstdlib>
#include <ctime>
using namespace std;
struct Node
{
    int value;
    Node *left, *right;
    Node(int value, Node *l = NULL, Node *r = NULL)
    {
        this->value = value;
        left = l;
        right = r;
    }
};
struct BST
{
    Node *root = NULL;
    void insert(int value)
    {
        cout<<"Inserting: "<<value<<endl;
        Node **current = &root;
        while(*current != NULL)
        {
            if(value >= (*current)->value)
            {
                current = &((*current)->right);
            }
            else current = &((*current)->left);
        }
        (*current) = new Node(value);
    }
    void remove(int value)
    {
        Node *toRemove = search(value);
        remove(toRemove);
    }
    void remove(Node *toReplace)
    {
        if(toReplace == NULL) return;
        Node *toBeReplacedWith = NULL;

        if(toReplace->left == NULL && toReplace->right == NULL)
        {
            delete toReplace;
            toReplace = NULL;
            return;
        }
        if((toReplace->left == NULL) ^ (toReplace->right == NULL))
        {
            if(toReplace->left != NULL) toBeReplacedWith = toReplace->left;
            else toBeReplacedWith = toReplace->right;
            copyAndDeleteNode(toReplace, toBeReplacedWith);
            return;
        }
        Node *current = toReplace->left;
        while(current->right != NULL) current = current->right;
        toReplace->value = current->value;
        remove(current);
    }
    Node* search(int value)
    {
        Node *current = root;
        while(current != NULL && current->value != value)
        {
            if(current->value > value) current = current->left;
            else current = current->right;
        }
        if(current == NULL)
        {
            cout<<"The node didn't exist in the BST";
        }
        return current;
    }
    void traverse()
    {
        rec_traverse(root);
    }
private:
    void copyAndDeleteNode(Node *toReplace, Node *toBeReplacedWith)
    {
        toReplace->value = toBeReplacedWith->value;
        toReplace->left = toBeReplacedWith->left;
        toReplace->right = toBeReplacedWith->right;
        delete toBeReplacedWith;
        toBeReplacedWith = NULL;
    }
    void rec_traverse(Node * current)
    {
        if(current == NULL) return;
        rec_traverse(current->left);
        cout<<current->value<<endl;
        rec_traverse(current->right);
    }
};
int main()
{
    BST tree;
    for(int i = 0; i < 10; ++i)
    {
        tree.insert(i);
    }
    Node  *a = tree.search(6);
    cout<<"found val: "<<a->value<<endl;

    tree.remove(5);
    tree.remove(9);
    tree.remove(2);
   // tree.insert(4);
    //tree.insert(15);
    tree.insert(6);
    tree.insert(22222);
    cout<<"Traversing:\n";
    tree.traverse();
    return 0;
}
#包括
#包括
#包括
#包括
使用名称空间std;
结构体类型
{
int值;
节点*左,*右;
节点(int值,节点*l=NULL,节点*r=NULL)
{
这个->值=值;
左=l;
右=r;
}
};
结构BST
{
Node*root=NULL;
无效插入(int值)
{
coutright==NULL)
{
删除或替换;
toReplace=NULL;
返回;
}
如果((存储替换->左==NULL)^(存储替换->右==NULL))
{
如果(toReplace->left!=NULL)ToReplacedWith=toReplace->left;
else toBeReplacedWith=toReplace->right;
copyAndDeleteNode(toReplace、ToReplacedWith);
返回;
}
节点*current=toReplace->left;
而(当前->右侧!=NULL)当前->右侧;
t更换->值=当前->值;
移除(当前);
}
节点*搜索(int值)
{
节点*当前=根;
while(当前!=NULL&¤t->value!=value)
{
如果(当前->值>值)当前=当前->左侧;
否则当前=当前->右侧;
}
如果(当前==NULL)
{
库特价值;
toReplace->left=TOBEREPLACED WITH->left;
toReplace->right=TOREPLACED WITH->right;
删除要替换的内容;
toBeReplacedWith=NULL;
}
无效记录遍历(节点*当前)
{
if(current==NULL)返回;
记录导线(当前->左侧);

有一件事是错误的,那就是:

删除(节点*toReplace)

该函数不会更新节点指针,因为您正在按值传递指针。该函数中所有以任何方式更改
toReplace
指针的代码在
remove
返回时都会被丢弃

例如,这些行:

delete toReplace;
toReplace = NULL;
delete
已完成,但将指针设置为NULL不会起任何作用,因为
toReplace
也是一个局部变量

您需要将原型更改为:

删除(节点*&toReplace)

现在,通过向指针传递引用,可以更新指针值并将其反射回调用方

此外,在删除“9”的叶节点后,您没有检查树的状态。如果这样做,您应该清楚地看到新的“8”叶节点的“右”指针不正确。当您尝试添加大于8的节点(22222)时,这会导致各种问题

您的
remove
功能在此处出现故障:

    if(toReplace->left == NULL && toReplace->right == NULL)
    {
        delete toReplace;
        toReplace = NULL;
        return;
    }
好的,那么您删除了节点(假设它是“9”节点)。那么以前指向“9”的节点呢?您没有将其右(或左)指针调整为现在指向NULL。这就是问题的根源

如果您只是在每次操作后查看树是否仍然正确,所有这些都可能被检测到。您可能只是使用了调试器,甚至只是在每个阶段打印出树的状态

最后,您的树结构缺少析构函数。您分配内存,但没有释放内存的地方

编辑:

这一行应该做什么?更具体地说,
^
应该做什么

if((toReplace->left == NULL) ^ (toReplace->right == NULL))  

<代码>由于某些原因在执行时,程序崩溃< /代码>使用调试器来确定问题的原因。值22222是第一个数据项还是在中间的某个位置?是否插入了值22222之前的多少个数据项?如果你想让我们为你调试程序,最低限度,我们需要你的测试数据。你试过了吗?其他值,它们成功还是失败?感谢您提供的信息,很高兴知道。但即使在进行更改(将指针传递给指针?)后,程序仍然会在插入时崩溃(22222)你能给我一个链接吗,因为我不知道怎么做。我的IDE是Code::Blocks,如果这很重要的话。我发现使用指针是C/C++中最难的部分,而且很难推理,例如,我花了1-2个小时才使代码正常工作,但仍然失败。请像我在这里做的那样做一个web搜索:好吧,如果我有“toReplace=NULL;”,这不是很有意义吗e父节点也指向NULL?至于^,我确保当前节点正好有一个子集,因此我可以将子节点放在当前节点的位置并维护BST属性。