为什么我的C++代码无法删除我的BST中的所有节点?

为什么我的C++代码无法删除我的BST中的所有节点?,c++,pointers,binary-tree,binary-search-tree,C++,Pointers,Binary Tree,Binary Search Tree,这将遍历BST并删除每个节点,包括根节点。然而,在最后,我得到的消息根仍然有一个左节点。为什么没有删除所有节点 void deleteTree() { deleteNode(root); if(root->right) cout << "root still has a right node" << endl; if(root->left) cout << "root still has

这将遍历BST并删除每个节点,包括根节点。然而,在最后,我得到的消息根仍然有一个左节点。为什么没有删除所有节点

void deleteTree()
{   
    deleteNode(root);
    if(root->right)
        cout << "root still has a right node" << endl;
    if(root->left)
        cout << "root still has a left node" << endl;
    root = 0;

}   

void deleteNode(node *p) 
{   
    if(p->left) 
    {   
        deleteNode(p->left);
        p->left = 0;
    }   
    if(p->right) 
    {   
        deleteNode(p->right);
        p->right = 0;
    }   

    cout << "Deleting node containing " << p->data << endl;
    delete p;
}   
您正在删除根末尾的p,然后尝试访问deleteTree中的内容,其中根不再指向已分配的内存。结果将是未定义的。

您正在删除根末尾的p,然后尝试在deleteTree中访问其内容,根不再指向已分配的内存。结果将是未定义的。

您正在删除根目录。然后你的代码试图访问它所在的内存

您已经进入了未定义的行为领域。

您正在删除root。然后你的代码试图访问它所在的内存


您已经进入了未定义的行为领域。

在deleteNode中删除root之后,不应该取消对它的引用。使用调试器检查root->left为何为非null。

在deleteNode中删除root之后,不应取消对其的引用。使用调试器检查为什么root->left为非null。

您在删除root之后查看root->left,使其可用于新分配的块。

您在删除root之后查看root->left,使其可用于新分配的块。

我只需更改树本身,那就更容易处理了:

struct Node
{
  Node(data_type data): mLeft(), mRight(), mData(data) {}
  Node(const Node& rhs): mLeft(), mRight(), mData(rhs.mData)
  {
    if (rhs.mLeft.get()) mLeft.reset(new Node(*rhs.mLeft));
    if (rhs.right.get()) mRight.reset(new Node(*rhs.mRight));
  }
  Node& operator=(Node rhs)
  {
    this->swap(rhs);
    return *this;
  }
  ~Node() { }

  void swap(Node& rhs)
  {
    using std::swap;
    swap(mLeft, rhs.mLeft);
    swap(mRight, rhs.mRight);
    swap(mData, rhs.mData);
  }

  Node* left() const { return mLeft.get(); }
  void left(std::auto_ptr<Node> node) { mLeft= node; }

  Node* right() const { return mRight.get(); }
  void right(std::auto_ptr<Node> node) { mRight = node; }

  data_type& data() { return mData; }
  const data_type& data() const { return mData; }

private:
  std::auto_ptr<Node> mLeft;
  std::auto_ptr<Node> mRight;
  data_type mData;
};

虽然C++可以防止意外的问题,但它对邪恶代码敞开了大门。

< p>我只需简单地改变树本身,就可以更容易地处理它:

struct Node
{
  Node(data_type data): mLeft(), mRight(), mData(data) {}
  Node(const Node& rhs): mLeft(), mRight(), mData(rhs.mData)
  {
    if (rhs.mLeft.get()) mLeft.reset(new Node(*rhs.mLeft));
    if (rhs.right.get()) mRight.reset(new Node(*rhs.mRight));
  }
  Node& operator=(Node rhs)
  {
    this->swap(rhs);
    return *this;
  }
  ~Node() { }

  void swap(Node& rhs)
  {
    using std::swap;
    swap(mLeft, rhs.mLeft);
    swap(mRight, rhs.mRight);
    swap(mData, rhs.mData);
  }

  Node* left() const { return mLeft.get(); }
  void left(std::auto_ptr<Node> node) { mLeft= node; }

  Node* right() const { return mRight.get(); }
  void right(std::auto_ptr<Node> node) { mRight = node; }

  data_type& data() { return mData; }
  const data_type& data() const { return mData; }

private:
  std::auto_ptr<Node> mLeft;
  std::auto_ptr<Node> mRight;
  data_type mData;
};

<如果> C++可以防止意外问题,它会给邪恶代码打开大门。

+ 1用于调试器建议,虽然我认为当函数返回时,他会发现它实际上是空的。“root”当然被删除了,但是在root -左边必须有别的东西。也许用调试器嗅探这个地址会发现一些东西…+1作为调试器的建议,尽管我认为他会发现,当函数返回时,它实际上是空的。“root”肯定被删除了,但在“root->left”处肯定还有其他东西;也许用调试器嗅探该地址会发现一些东西…为什么它在检查右节点时没有找到任何东西,但在检查左节点时却发现了一些东西?因为root只是指向垃圾内存。其他结果可能包括left only、both、note或崩溃。为什么当它检查右节点时,什么也找不到,但当它检查左节点时,却发现了什么?因为root只是指向垃圾内存。其他结果可能包括只左,两者都有,两者都没有,或者崩溃。