C++ 通过引用传递指针未按预期工作

C++ 通过引用传递指针未按预期工作,c++,pointers,pass-by-reference,binary-search-tree,C++,Pointers,Pass By Reference,Binary Search Tree,我编写代码递归地从BST中删除节点,主要是为了实现recurion并验证我对所使用的某些编码元素的理解。在这种情况下,问题似乎在于通过引用将指针传递到我的BST节点 我的BST代码的psrt如下所示。(这不是我要实现或使用的代码。只是一个练习。我选择BST作为示例来实现一些我想在该语言中尝试的东西) 标题- //BST.h class TNode { public: TNode():data(0), left(0), right(0) {} int data; TNode

我编写代码递归地从BST中删除节点,主要是为了实现recurion并验证我对所使用的某些编码元素的理解。在这种情况下,问题似乎在于通过引用将指针传递到我的BST节点

我的BST代码的psrt如下所示。(这不是我要实现或使用的代码。只是一个练习。我选择BST作为示例来实现一些我想在该语言中尝试的东西)

标题-

//BST.h
class TNode
{
public:
    TNode():data(0), left(0), right(0) {}
    int data;
    TNode* left;
    TNode* right;
};

class BST
{
private:
    TNode* Head;

public:
    BST();

    void InsertData(int data);
    void InsertNode(TNode* node);
    void DeleteData(int data);

private:
    void InsertDataPrivate(int data, TNode* &root); 
    void InsertNodePrivate(TNode* node, TNode* &root);
    void DeleteDataPrivate(int data, TNode* &root);
};
CPP-

在最后一步中,我说
bst.DeleteData(77)我有个问题。具有“77”的节点将被删除,并以“78”替换,其方式是从BST中删除具有两个子节点的节点。但是,在删除之前具有“78”的节点后,具有“77”的父节点仍然指向非空位置

我正在调用我的私有函数
DeleteDataPrivate(int-data,TNode*&root)
在删除TNode指针后将其设置为NULL。我还在函数中通过引用传递指针,以便在递归堆栈展开时将空值分配给已删除的节点指针。这种情况不会发生。有人能解释一下我做错了什么吗

多谢各位

钦梅

更新

根据Dan在下面的评论,问题在于将值传递给局部变量,这些变量复制了我的指针,并且没有分配回任何对象。我已经修改了我的函数,通过使用指向指针的指针来解释这一点,从而使展开递归返回的TNode指针的值存储在内存中的正确位置,而不是存储在TNode指针的某个副本中

修改后的函数如下所示

void BST::DeleteDataPrivate(int data, TNode* &root)
{
    if( 0 == root ) return;

    if( root->data == data )
    {
        if(0 == root->left && 0 == root->right)
        {
            delete root;
            root = 0;
        }
        else if(0 == root->left)
        {
            TNode* current = root;
            root = root->right;
            delete current;
            current = 0;
        }
        else if(0 == root->right)
        {
            TNode* current = root;
            root = root->left;
            delete current;
            current = 0;
        }
        else
        {
            TNode* biggestOnLeft = root->left;
            TNode* smallestOnRight = root->right;
            int i = 0;
            while (biggestOnLeft->right) // check if left subtree is longer than right subtree
            {
                biggestOnLeft = biggestOnLeft->right;
                --i;
            }
            while (smallestOnRight->left)
            {
                smallestOnRight = smallestOnRight->left;
                ++i;
            }
            TNode** locationOfDeletedNode = 0;
            if(i < 0) // left subtree is longer than right subtree
            {

                locationOfDeletedNode = &(root->left);
                while(*locationOfDeletedNode != biggestOnLeft) locationOfDeletedNode = &((*locationOfDeletedNode)->right);
            }
            else // right subtree is longer than or equal in size to left subtree
            {
                locationOfDeletedNode = &(root->right);
                while(*locationOfDeletedNode != smallestOnRight) locationOfDeletedNode = &((*locationOfDeletedNode)->left);

            }
            root->data = (*locationOfDeletedNode)->data;
            DeleteDataPrivate((*locationOfDeletedNode)->data, *locationOfDeletedNode);
        }
    }
    else if(data < root->data && 0 !=root->left)
    {
        DeleteDataPrivate(data, root->left);
    }
    else if(data > root->data && 0 !=root->right)
    {
        DeleteDataPrivate(data, root->right);
    }
}
void BST::DeleteDataPrivate(int-data,TNode*&root)
{
如果(0==根)返回;
如果(根->数据==数据)
{
如果(0==根->左&0==根->右)
{
删除根;
根=0;
}
else if(0==根->左)
{
t节点*电流=根;
根=根->右;
删除当前文件;
电流=0;
}
else if(0==根->右)
{
t节点*电流=根;
根=根->左;
删除当前文件;
电流=0;
}
其他的
{
TNode*biggestOnLeft=root->left;
TNode*smallestorright=root->right;
int i=0;
while(biggestOnLeft->right)//检查左子树是否比右子树长
{
biggestoleft=biggestoleft->right;
--一,;
}
while(smallestorright->left)
{
smallestorright=smallestorright->left;
++一,;
}
TNode**locationOfDeletedNode=0;
if(i<0)//左子树比右子树长
{
locationOfDeletedNode=&(根->左);
而(*locationOfDeletedNode!=biggestOnLeft)locationOfDeletedNode=&((*locationOfDeletedNode)->右侧);
}
else//右子树的大小大于或等于左子树
{
locationOfDeletedNode=&(根->右);
而(*locationOfDeletedNode!=smallestorright)locationOfDeletedNode=&((*locationOfDeletedNode)->左);
}
根->数据=(*locationOfDeletedNode)->数据;
DeleteDataPrivate((*locationOfDeletedNode)->数据,*locationOfDeletedNode);
}
}
else if(数据data&&0!=root->left)
{
DeleteDataPrivate(数据,根->左);
}
否则如果(数据>根->数据和0!=根->右)
{
DeleteDataPrivate(数据,根->右侧);
}
}

当然,这可以构造得更好,但我的目标是在这里学习简单但棘手的东西,多亏了Dan和其他人,我在这里做到了这一点。

不能通过引用TNode为指针赋值NULL,因为引用变量不能为NULL。请参见

您不能通过引用TNode为指针分配NULL,因为引用变量不能为NULL。打电话时请参见

DeleteDataPrivate(biggestOnLeft->data, biggestOnLeft);
它只分配给局部变量
biggestOnLeft
,而不分配给任何对象的成员

因为当你这么做的时候

TNode* biggestOnLeft = root->left;
它创建了一个新变量,它是
root->left
的副本,与此不同

固定想法 您可以尝试在根目录下启动
biggestleft
smallestorright
,然后执行以下操作

while (biggestOnLeft->right->right) 
然后你可以打电话

DeleteDataPrivate(biggestOnLeft->data, biggestOnLeft->right);
免责声明:我没有测试过这个,可能是打错了什么。

当你打电话时

DeleteDataPrivate(biggestOnLeft->data, biggestOnLeft);
它只分配给局部变量
biggestOnLeft
,而不分配给任何对象的成员

因为当你这么做的时候

TNode* biggestOnLeft = root->left;
它创建了一个新变量,它是
root->left
的副本,与此不同

固定想法 您可以尝试在根目录下启动
biggestleft
smallestorright
,然后执行以下操作

while (biggestOnLeft->right->right) 
然后你可以打电话

DeleteDataPrivate(biggestOnLeft->data, biggestOnLeft->right);

免责声明:我没有测试过这个,可能是打错了什么。

你能展示一下方法
DeleteDataPrivate()
?@noMAD-它在BST.cpp.dam中,这个卷轴有时会让你抓狂。无论如何,你得到了一个修正:)@DavidHammen我会接受这个修正,因为它确实告诉我哪里错了,我现在明白了。我只是想解决这个问题,这样我就可以更新并结束这个话题。过去,当我无法获得令人信服的问题解决方案时,我没有接受答案。我认为这样做是不对的。不过,我确实觉得所有的帮助都很有用,对此我表示感谢。干杯:)你能展示方法
DeleteDataPrivate()
?@noMAD-它在BST.cpp.dam中,这个滚动的东西有时会让你抓狂。不管怎样,你得到了一个解决办法:)@DavidHammen我会接受这个解决办法的