删除函数调用后为什么指针不是BST的归零节点?

时间:2016-09-15 18:28:54

标签: c pointers binary-search-tree

为BST设置一个递归删除函数,该函数不会将指针归零到叶节点。

bool removeNode(Node* tree, int key)
{
    bool removed = false;

    if (tree)
    {
        if (key < tree->key)
        {
            removeNode(tree->left, key);
        }
        else if (key > tree->key)
        {
            removeNode(tree->right, key);
        }
        else // this node is the key
        {
            if (!tree->left && !tree->right) // leaf
            {
                free(tree);
                tree = 0;
            }
            else if (!tree->left)
            {
                *tree = *tree->right;
            }
            else if (!tree->right)
            {
                *tree = *tree->left;
            }
            else // this node has 2 children
            { 
                Node* paux = tree->left;

                if (paux->right)
                {
                    while (paux->right)
                    {
                        paux = paux->right;
                    }
                }

                tree->key = paux->key;
                tree->left = paux->left;
            }

            removed = true;
        }
    }

    return removed;
}

我用

Node* node = (Node*)malloc(sizeof(Node));

分配内存。我的叶子地址被正确归零,但当它返回上一次呼叫时,地址仍然保持不变。如果地址归零,为什么它会返回到先前的值?这个改变应该影响指针......不应该吗?

数据结构和相关功能:

typedef struct Node
{
    int key;
    struct Node* left;
    struct Node* right;
} Node;

// init a binary tree
void init(Node** tree, int key)
{
    *tree = (Node*) malloc(sizeof(Node));

    (*tree)->key = key;
    (*tree)->left = 0;
    (*tree)->right = 0;
}

// insert at binary tree
bool insert(Node** tree, int key)
{
    bool inserted = false;

    if (!*tree)
    {
        init(&*tree, key);
    }
    else
    {
        Node* node = (Node*)malloc(sizeof(Node));
        node->key = key;
        node->left = 0;
        node->right = 0;

        Node* paux = *tree;
        Node* root = paux;

        while (paux != 0)
        {
            root = paux;

            if (key < paux->key)
            {
                paux = paux->left;
            }
            else
            {
                paux = paux->right;
            }
        }

        paux = node;
        if (key < root->key)
        {
            root->left = paux;
        }
        else
        {
            root->right = paux;
        }

        inserted = true;
    }

    return inserted;
}

void print(Node* tree)
{
    if (tree != 0)
    {
        printf("%d  ", tree->key);

        print(tree->left);
        print(tree->right);
}

3 个答案:

答案 0 :(得分:4)

遇到的问题是因为函数无法修改输入指针。指针本身按值传递。

考虑一个递增整数的函数。这个简单的实现不会起作用,因为参数传递了#34;值#34;。

void inc(int x)
{
    x++;
}

您可以通过引用(指针)

来传递此示例
void inc(int *x)
{
    (*x)++;
}

所以,如果你想能够在函数内使指针无效,则传递一个指向指针的指针:

bool removeNode(Node **tree, int key)

答案 1 :(得分:3)

由于您希望能够在函数内部更改tree,因此需要双指针。

而不是

bool removeNode(Node* tree, int key)

你需要

bool removeNode(Node** tree, int key)
                    ^^

这也意味着您需要更改在函数内访问tree的方式。

另见:https://stackoverflow.com/a/39436538/4386427 - 这是同样的问题

答案 2 :(得分:1)

removeNode()拥有自己的tree副本,因此在tree之外无法看到对removeNode()本身实际值的更改。其中一个选项是将tree设为Node **,正如其他人所建议的那样。另一种选择是重构,以便在要释放节点的位置使父节点指针可用。例如,父项可以作为另一个参数传递给removeNode(),或者您的代码可以在处理时更深入地测试一个级别。然后你可以做free(parent->left); parent->left=0;或其他一些。