c ++删除节点会破坏排序算法

时间:2018-03-27 10:31:41

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

我正在尝试为二叉搜索树实现递归删除算法,并且已经成功完成了但是它打破了排序算法(依次,预订和后序)。继承我的删除功能代码

void remove_rec(string word, Node* ptr) {

        if (word < ptr->data && ptr->left != nullptr) {
            remove_rec(word, ptr->left);
        }
        else if (word > ptr->data && ptr->right != nullptr) {
            remove_rec(word, ptr->right);
        }
        else {
            //if the node has no children
            if (ptr->left == nullptr && ptr->right == nullptr) {
                delete(ptr);
                ptr = nullptr;
            }
            //if there is a right child
            else if (ptr->left == nullptr && ptr->right != nullptr) {
                Node* temp = ptr;
                ptr = ptr->right;
                delete temp;
            }
            //if there is a left child
            else if (ptr->left != nullptr && ptr->right == nullptr) {
                Node* temp = ptr;
                ptr = ptr->left;
                delete temp;
            }
        }
    }

当递归调用inorder(或任何其他排序方法)并且左或右节点为空时,程序似乎崩溃。程序不是跳过if语句,而是继续尝试访问左节点,直到它崩溃并出现错误“读取访问冲突”。如果我不调用remove_rec函数,则排序函数按预期工作。对我来说,似乎我在删除节点后没有正确构建树。任何帮助深表感谢!我只包括我认为导致问题的代码,如果没有调用该函数,一切都按预期工作。

1 个答案:

答案 0 :(得分:0)

您没有修改您认为自己的指针。行

ptr

修改本地参数Node,它是您ptr个孩子之一的独特副本。您需要通过引用传递delete以使修改生效。

您获得“读取访问权限”的原因是因为节点中指针的仍然与删除之前相同,但它现在无效,因为您{{ 1}} d对象。

您也在复制您要搜索的数据,效率很低。

void remove_rec(const std::string & word, Node *& ptr) {
    if (word < ptr->data && ptr->left != nullptr) {
        remove_rec(word, ptr->left);
    }
    else if (word > ptr->data && ptr->right != nullptr) {
        remove_rec(word, ptr->right);
    }
    else {
        //if the node has no children
        if (ptr->left == nullptr && ptr->right == nullptr) {
            delete(ptr);
            ptr = nullptr;
        }
        //if there is a right child
        else if (ptr->left == nullptr && ptr->right != nullptr) {
            Node* temp = ptr;
            ptr = ptr->right;
            delete temp;
        }
        //if there is a left child
        else if (ptr->left != nullptr && ptr->right == nullptr) {
            Node* temp = ptr;
            ptr = ptr->left;
            delete temp;
        }
        // TODO: handle case when node has both left and right child
    }
}

另外,我会将Node更改为使用std::unique_ptr<Node> leftright。如果您将来犯同样的错误,则会出现编译时错误。