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

时间:2010-02-11 02:57:15

标签: c++ pointers binary-tree binary-search-tree

这应该遍历BST并删除每个节点,包括根节点。但是,最后,我收到消息“root仍然有一个左节点”。为什么不删除所有节点?

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

5 个答案:

答案 0 :(得分:6)

您最后会删除proot),然后尝试访问deleteTree()中的内容,其中root不再指向已分配的内存。结果将是未定义的。

答案 1 :(得分:2)

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

你很熟悉那里的未定义行为。

答案 2 :(得分:2)

root中将其删除后,您不应取消引用deleteNode。使用调试器检查root->left为非空的原因。

答案 3 :(得分:2)

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

答案 4 :(得分:-1)

我只想更改树本身,然后处理它会更容易:

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

通过面向对象,每个节点现在负责它处理的内存。此外,在界面中使用std::auto_ptr可以清楚地表明它需要所有权。

请注意,它是专为深度复制而设计的,任何其他需要boost::shared_ptr或等效的方法。是的std::auto_ptr让你自己处理复制,没有魔法。

这种设计比使用普通C-struct更清晰,每个人都可以操纵资源。您仍然可以通过访问者完全访问基础数据......但是他们注意不要调用未定义的行为...

当然,你仍然可以将其崩溃:

Node& node = ...
delete node.left(); // haha

但是,如果C ++可以防止出现意外问题,那么就会让邪恶的代码敞开大门。