1

I think there are multiple errors in my code for deleting a node from a BST. I just can't figure out what! Here's my code. Thanks in advance!

void del(int val){
    help = root;
    f = help;
    while (help){
        if(help->data==val) break;
        f  = help;
        if (val > help-> data) help = help->right;
        else help = help->left;
    } if(help->data != val) printf("\nElement not found!");
    else{
        printf("Element found!");
        target = help;
        if(val>f->data){
            if(target->right && !target->left) {f->right = target->right; f = target->right;}
            else {f->right = target->left; f = target->left;}
        } else{
            if(target->right && !target->left) {f->left = target->right; f = target->right;}
            else {f->left = target->left; f = target->left;}
        }
        while(help ->right) help = help->right;
        if(help->left) help = help->left;
        f->right = help;
        free(target);
    }
}
3
  • 1
    You should always post the error messages and the things which are going wrong according to you, in order to help others to help you. Commented Sep 1, 2013 at 5:40
  • Agree with @Uchia. Infact, you probably should paste the code where you build and insert values into the tree. This way, it would be easier to test your code. Commented Sep 1, 2013 at 5:41
  • There are literally a dozen related questions to this one in the Related list on the side of this page. I'm having a difficult time picking one to list as a dupe right now. This one shows some promise Commented Sep 1, 2013 at 6:05

2 Answers 2

0

One error that I spot is that if one were to delete the left node in the tree, then the last few lines might not work since they are not symmetric. So, let us say, the tree has root as 6 and left-child as 4 and right-child as 8. Now, you want to delete 4. So, after you have found the node in the first while clause, you would hit the else clause of "if (val > f->data){". At this point, f would point to 6, target and help would point to 4. Now, you are setting the left of f to right of target, so left of 6 would point to NULL and f itself would point to NULL. So, far so good! But, once you get into the while loop, since help has no right node, help would continue to point to 6. In the end, you make the right node of f (btw, f is already NULL at this point) to help and you would actually end up crashing!

while (help->right)
     help = help->right;

if (help->left)
      help = help->left;

f->right = help;

Another error is that you do not update the root pointer, incase you end up deleting the root node.

One simpler approach would be to divide this into three cases. I am providing code for all the three cases. Use a sample tree for each of these three cases and then debug/test it.

First, if the found node (which your file while loop is doing) has no child nodes, then delete it and set its parent to NULL and you are done. Here is a rough-first cut of the first case:

    /* If the node has no children */
    if (!help->left && !help->right) {
        printf("Deleting a leaf node \n");
        f = help->parent;
        if (f) {
            if (value > f->value)
                f->right = NULL;
            else
                f->left = NULL;
        }
        /* If deleting the root itself */
        if (f->value == root) {
            root = NULL;
        }
        free(help);
        return 0;
    }

Second, if the found node has only child (left or right), then splice it out and the child of the found node becomes hte child of the parent node. Here is the second case:

    /* If the node has only one child node */
    if ((help->left && !help->right)
        || (!help->left && help->right)) {
        printf("Deleting a node with only one child \n");
        f = help->parent;

        if (help->left)  {
            child_node = help->left;
        } else  {
            child_node = help->right;
        }

        if (f) {
            if (value > f->value) {
                f->right = child_node;
            } else  {
                f->left = child_node;
            }
        } else {
            /* This must be the root */
            root = child_node;
        }
        free(help);
        return 0;
    }

The third case is tricky -- here the found node has two child nodes. In this case, you need to find the successor of the node and then replace the value of the found node with the successor node and then delete the successor node. Here is the third case:

    /* If the node has both children */
    if (help->left && help->right) {
        successor_found = find_successor(help, help->data);
        printf("Deleting a node with both children \n");
        if (successor_found) {
            successor_value = successor_found->value;
            del(successor_found->value);
            help->value = successor_value;
        }
        return 0;
    }

And, here is the code to find successor:

binary_node_t *node find_successor(binary_node_t *node, int value) {

    binary_node_t *node_found;

    if (!node) {return NULL; }

    node_found = node;
    old_data = node->data;

    /* If the node has a right sub-tree, get the min from the right sub-tree */
    if (node->right != NULL) {
        node = node->right;
        while (node) {
            node_found = node;
            node = node->left;
        }
        return node_found;
    }

    /* If no right sub-tree, get the min from one of its ancestors */
    while (node && node->data <= old_data) {
        node = node->parent;
    }
    return (node);
}
Sign up to request clarification or add additional context in comments.

Comments

0
typedef struct xxx {
        struct xxx *left;
        struct xxx *right;
        int data;
        } ;
#define NULL (void*)0
#define FREE(p) (void)(p)

void treeDeleteNode1 (struct xxx **tree, int data)
{
    struct xxx *del,*sub;

        /* Find the place where node should be */
    for (       ; del = *tree; tree = (data < del->data) ? &del->left : &del->right ) {
        if (del->data == data) break;
        }
        /* not found: nothing to do */
    if ( !*tree) return;

        /* When we get here, `*tree` points to the pointer that points to the node_to_be_deleted
        ** If any of its subtrees is NULL, the other will become the new root
        ** ,replacing the deleted node..
        */
    if ( !del->left) { *tree = del->right; FREE(del); return; }
    if ( !del->right) { *tree = del->left; FREE(del); return; }

        /* Both subtrees non-empty:
        ** Pick one (the left) subchain , save it, and set it to NULL */
    sub = del->left;
    del->left = NULL;

        /* Find leftmost subtree of right subtree of 'tree' */
    for (tree =  &del->right; *tree; tree =  &(*tree)->left) {;}
        /* and put the remainder there */
    *tree = sub;
    FREE(del);
}

To be called like:

...
struct xxx *root;
...
treeDeleteNode1( &root, 42);
...

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.