这应该遍历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;
}
答案 0 :(得分:6)
您最后会删除p
(root
),然后尝试访问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 ++可以防止出现意外问题,那么就会让邪恶的代码敞开大门。