我做了一个二叉搜索树(节点)类:
class BstNode {
public:
BstNode(int value);
~BstNode();
BstNode* Delete(int value);
// more methods
private:
int value_;
BstNode* left_;
BstNode* right_;
};
具有如下所示的析构函数:
BstNode::~BstNode() {
delete left_;
delete right_;
}
还有一个Delete
函数:
BstNode* BstNode::Delete(int value) {
// If the value to be deleted is smaller than the root's key,
// then it lies in the left subtree.
if (value < value_) {
if (left_ == nullptr) return nullptr;
else left_ = left_->Delete(value);
}
// If the value to be deleted is larger than the root's key,
// then it lies in the right subtree.
else if (value > value_) {
if (right_ == nullptr) return nullptr;
else right_ = right_->Delete(value);
}
// If the key to be deleted is the same as root's key, then *this*
// is the node to be deleted.
else {
// If this node has no children, then we can just delete it.
if (left_ == nullptr && right_ == nullptr) {
delete this;
return nullptr;
}
// If this node has one child, then we can just set this node to
// that child and delete this node afterwards.
else if (left_ == nullptr) {
BstNode* temp = right_;
delete this;
return temp;
}
else if (right_ == nullptr) {
BstNode* temp = left_;
delete this;
return temp;
}
// If this node has two children, then we have to get the "in-order successor"
// (the smallest node in the right subtree).
else {
BstNode *temp = right_->Smallest();
// Copy that node's value to this node
value_ = temp->value_;
// Then delete that value from the right subtree
right_ = right_->Delete(value_);
}
}
return this;
}
我很困惑的是这个片段:
else if (left_ == nullptr) {
BstNode* temp = right_;
delete this;
return temp;
}
else if (right_ == nullptr) {
BstNode* temp = left_;
delete this;
return temp;
}
如果对delete
的调用调用了该类的析构函数,我是否最终会删除整个子树(右侧或左侧)?但是,在测试时,看起来树确实在执行我要执行的操作:删除节点,并将子子树“移动”到“ this”所在的位置-子树仍然完整。
据我所知,BstNode* temp = this;
只是将 pointers 复制到left_
和right_
,然后delete this
调用应该销毁他们背后的数据。
我是否缺少有关delete this
的东西?
答案 0 :(得分:3)
BstNode* temp=left_
和BstNode* temp=right_
会将left_或right_的值存储在一个临时变量中。在临时存储该值后,您正在使用delete this;
。现在,在使用delete this;
之后,left_和right_将被删除,但temp仍将保持不变。 delete this;
不会影响temp的值(它具有您的左/右子树),并且您现在可以在删除相应的右/左子树后返回相应的左/右子树(在这种情况下, left_或right_都指向NULL)。我希望这有帮助!
另外,在指向未分配有new的对象的指针上使用delete会产生不可预测的结果,因此请务必小心!
答案 1 :(得分:2)
由于您的BstNode
析构函数同时删除了left_
和right_
节点,因此,由于以下顺序,您会遇到未定义行为:
BstNode* temp = right_;
delete this;
return temp;
在delete this
语句之后,temp
将成为悬空指针,因为它指向的对象已被删除。返回该指针,然后将其存储回另一个节点,最终在取消引用该节点时,可能会发生任何事情-包括程序似乎正常工作。
您应在调用Delete之前将right_
设置为nullptr
,或更改析构函数(以及整体销毁顺序)以不删除子节点。