C中的二进制搜索树:删除节点功能

时间:2013-02-19 08:50:00

标签: c data-structures binary-search-tree

我正在为二元搜索树组合函数并遇到一堵墙。我正在处理需要从树中删除保存指定值的节点时可能遇到的每种情况。我不确定如果它没有左右孩子,如何处理释放节点。该函数必须返回一个节点。我是否会备份,检查每个左右孩子,并在孩子身上移除该值?但是,如果值在根目录中,我是否会遇到类似的问题如何删除它?仅作为解释,程序使用void指针,然后在单独的函数compare()中强制转换TYPE值,该函数计算两个值并为<返回-1,对于==,返回1,对于>,返回1。

struct Node *_removeNode(struct Node *cur, TYPE val)
{
    if (compare(cur->val, val) == 0) { //if val == cur->val
        if (cur->right != NULL && cur->left != NULL) { //if cur has right and left
            cur = _leftMost(cur->right);
            free(_leftMost(cur->right));
        }
        else if (cur->right == NULL && cur->left != NULL) {  //if cur has left
            cur = cur->left;
            free(cur->left);
        }
        else if (cur->right != NULL && cur->left == NULL){ //if cur has right
            cur = cur->right;
            free(cur->right);
        }
        else if (cur->right == NULL && cur->left == NULL){ //if cur has no child
                //free cur if cur = val

        }
    }
    else if (compare(cur->val, val) == -1) {
        cur->right = _removeNode(cur->right, val);
    }
    else if (compare(cur->val, val) == 1) {
        cur->left = _removeNode(cur->left, val);
    }

    return cur;
}

1 个答案:

答案 0 :(得分:2)

如果节点没有子节点,则可以简单地删除它。为了使其他情况下的递归起作用,您应该从_removeNode返回NULL。在所有情况下,应删除(释放)cur,因为不再需要它。在每种情况下,您都需要返回替换子树。并发症发生在第一种情况,其中右儿童的最左后裔被拉起。将其拉起后,您需要将其从右侧子树中删除(请注意,它可能是正确的子树)。

我把以下所有内容写在了脑海中,所以要为一些错误/一些调试做好准备。此外,_leftMost和_removeLeftMost可以合并一些工作。

有问题的块应该类似于:

    Node *replacement;
    if (cur->right != NULL && cur->left != NULL) { //if cur has right and left    
        replacement = _leftMost(cur->right);
        replacement->right = _removeLeftMost(cur->right,replacement);
        replacement->left = cur->left;
    }
    else if (cur->right == NULL && cur->left != NULL) {  //if cur has left
        replacement = cur->left;
    }
    else if (cur->right != NULL && cur->left == NULL){ //if cur has right
        replacement = cur->right;
    }
    else if (cur->right == NULL && cur->left == NULL){ //if cur has no child
        replacement = NULL;
    }
    free(cur);
    cur = replacement;

函数_removeLeftMost向下遍历左子指针,直到它看到要替换的节点,然后用该节点的右子节点替换它。类似的东西:

Node *_removeLeftMost(node, remove) {
    if (node == remove) {
       return node->right; // Note that remove->left should be null
    }
    else {
       node->left = _removeLeftMost(node->left,remove);
       return node;
    }
}

此外,主要电话类似于

root = _removeNode(root, val);

因此,当节点是根时,处理您的问题。