在二叉搜索树功能中使用指向指针的指针时出错

Error when working with pointer to a pointer in Binary Search Tree functionality

本文关键字:指针 出错 搜索树 功能      更新时间:2023-10-16

我有以下代码:

#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;
}

由于某些原因,在执行时,程序在insert(22222)上崩溃,而之前的调用没有问题,我不明白为什么。问题必须在第26-30行之间,我总是在节点构造函数中放置NULL值,所以我很困惑为什么循环不会中断。

有一件事是错误的:

remove(Node* toReplace)

该函数不更新您的Node指针,因为您是按值传递指针。只要remove返回,该函数中以任何方式改变toReplace指针的所有代码都将被丢弃。

例如:

delete toReplace;
toReplace = NULL;

delete完成了,但是将指针设置为NULL没有任何作用,因为toReplace是一个局部变量。

你需要把你的原型改成这样:

remove(Node *& 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))