删除二进制搜索树(C ++)中的单个元素

时间:2018-09-10 04:04:50

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

我做了一个二叉搜索树(节点)类:

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的东西?

2 个答案:

答案 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,或更改析构函数(以及整体销毁顺序)以不删除子节点。