Deleting the lowest value in a binary search tree

寵の児 提交于 2020-01-25 17:22:21

问题


I wrote this and somehow it's ending up deleting all my left side on the tree not only the most left leaf.

I can't find my mistake, can someone help?

struct Node *delMin(struct Node **root)
{
    struct Node *current = *root;
    struct Node *b4Current;

    while ((current->m_ls) == NULL) {
        b4Current = current;
        current = current->m_ls;
    }

    if ((current->m_rs) == NULL) {
        b4Current->m_ls = 0;
        free(current);
    } else {
        b4Current->m_ls = current->m_rs;
        free(current);
    }

    return *root;
}

回答1:


Let's look at your function.

struct Node *delMin(struct Node **root)

You take a pointer to node pointer as argument and return the new head. That is unnecessary. Returning the head is only useful if it isn't updated otherwise. Your pointer-to-node-pointer approach caters for that (well, it should, but it doesn't), so that the return value is free for other information.

    struct Node *b4Current;

Here, you define an uninitialised pointer. You should initialise it to NULL to idicate that the current node, the head, doesn't have a parent. Otherwise the pointer will be a garbage value that is likely to cause undefined behaviour.

    while ((current->m_ls) == NULL) {
        b4Current = current;
        current = current->m_ls;
    }

Here, your condition is wrong: You want to go left as long as there is a pointer, but you do something else: You go left if there isn't anywhere to go! When the head has a left child, current will stay at the head. Otherwise, it will be NULL, which will cause havoc when you try to dereference it later.

    if ((current->m_rs) == NULL) {
        b4Current->m_ls = 0;
        free(current);

    } else {
        b4Current->m_ls = current->m_rs;
        free(current);
    }

The two branches of the if are really the same, if you think about. It's a bit like saying: if (x == 0) y = 0; else y = x;.

But you need an if here, namely to distinguish between the case that current is the head or not. In the former case, you should update *head, the latter case is what you have already written.

You should also catch the case that you can't remove a node from an empty list.

So:

void delMin(struct Node **root)
{
    struct Node *current = *root;
    struct Node *b4Current = NULL;

    if (current == NULL) return NULL;

    while (current->m_ls != NULL) {
        b4Current = current;
        current = current->m_ls;
    }

    if (b4Current == NULL) {
        *root = current->m_rs;
    } else {
        b4Current->m_ls = current->m_rs;
    }

    free(current);
}

But since you are passing a pointer to your head node anyways, you could simplify the function to:

void delMin(struct Node **root)
{
    if (*root == NULL) return;

    while ((*root)->m_ls != NULL) {
        root = &(*root)->m_ls;
    }

    struct Node *old = *root;

    (*root) = (*root)->m_rs;
    free(old);
}

You may have some ugly (*root)s here, but you do away with a lot of auxiliary variables and if statements. The idea is that you add one level of indirection by iterating with a pointer to node pointer. *root takes the role of your b4Current and (*root)->m_ls is your current, except that *root starts with a sensible initial value, namely the root node.




回答2:


I believe your problem is in your while loop condition. You want to be traversing the left side of the tree while current->m_ls != NULL, otherwise you will delete the entire left side of you tree.



来源:https://stackoverflow.com/questions/30219315/deleting-the-lowest-value-in-a-binary-search-tree

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!