删除BST节点:失败三连败

时间:2019-11-16 02:16:58

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

提醒一下,我想在2年前提交此代码,但想尝试定期对其进行重新访问,以查看是否可以修复它。我理解逻辑,但是我的指针必须有些错误。我最终做出了三个单独的尝试。没有工作。大部分代码是由教授编写的,我实现的其他功能也很好。不幸的是,他没有给我任何指示(双关语意)如何进行删除。每次都是一样的故事:指针混乱和读取访问冲突。这是我的三种尝试之一:

template <typename K, typename T>
void BST<K, T>::remove(const K& k)
 Attempt 1
     If p is a nullptr, return. 
    if (p == nullptr)
        return;
    // If the key is greater than the p's key, go down the right subtree
    if (k > p->key)
        remove(p->right, k);
    // If it's less, then it's in the left subtree
    else if (k < p->key)
        remove(p->left, k);
    // If key is found
    else if (p->key == k) {
        // And it has both children
        if (p->left && p->right) {
            Node *q = findMin(p->right);
            p->key = q->key;
            p->data = q->data;
            remove(p->right, k);
        }
        else if (p->right) {
            // Copy right child to p and delete p
            p->key = p->right->key;
            p->data = p->right->data;
            p->parent->right = p->right;
            p->right->parent = p->parent;
            delete p;
            p = nullptr;
        }
        // If it only has left child
        else if (p->left) {
            // Copy left child to p and delete p
            p->key = p->left->key;
            p->data = p->left->data;
            p->parent->left = p->left;
            p->left->parent = p->parent;
            delete p;
            p = nullptr;
        }
        else {
            if (p->parent->left = p)
                p->parent->left = nullptr;
            else
                p->parent->right = nullptr;
            delete p;
        }
    }

此函数由我的教授编码的函数调用:

template <typename K, typename T>
void BST<K, T>::remove(const K& k) {
    if (root && root->key == k) {
        Node*p = root;
        if (root->left&&root->right) {
            Node*q = findMin(root->right);
            root->key = q->key;
            root->data = q->data;
            remove(root->right, k);
        }
        else {
            if (root->left)
                root = root->left;
            else if (root->right)
                root = root->right;
            else
                root = nullptr;
            delete p;
        }
    }
    else
        remove(root, k);
}

1 个答案:

答案 0 :(得分:0)

我终于把它处理了。我的问题很多:

1)remove(root->right, k);

如以上注释中所述,k被新密钥覆盖,并且在树中不再存在。我之前已经对此行进行过更改,但这不是我遇到的唯一问题。

2)p->parent->right = p->right; p->right->parent = p->parent;

节点有一个正确的孩子,不一定是一个本身的正确孩子。左边的子语句也是如此。

3)delete p; p = nullptr;

在这些陈述中隐含的事实是,由于它只有一个孩子,所以该孩子是一片叶子。它很可能是子树的父节点。

更正的代码:

    // If p is a nullptr, return. 
    if (p == nullptr)
        return;
    // If the key is greater than the p's key, go down the right subtree
    else if (k > p->key)
        remove(p->right, k);
    // If it's less, then it's in the left subtree
    else if (k < p->key)
        remove(p->left, k);
    // If key is found
    else if (p->key == k) {
        // And it has both children
        if (p->left && p->right) {
            Node *q = findMin(p->right);
            p->key = q->key;
            p->data = q->data;
            remove(p->right, q->key);
        }
        else if (p->right) {
            // Copy right child to p and delete p
            p->key = p->right->key;
            p->data = p->right->data;
            remove(p->right, p->right->key);
        }
        // If it only has left child
        else if (p->left) {
            // Copy left child to p and delete p
            p->key = p->left->key;
            p->data = p->left->data;
            remove(p->left, p->left->key);
        }
        else {
            if (p == p->parent->left) 
                p->parent->left = nullptr;
            else if (p == p->parent->right) 
                p->parent->right = nullptr;
            else
                p = nullptr;
            delete p;
        }
    }
}