如何删除BST C语言中的子树?

时间:2012-06-10 06:53:13

标签: c binary-search-tree subtree

我想制作pop函数来删除节点的节点和子树。这是我的代码

void pop(struct data *node,int num)
{
    if(node)
    {
        if(node->num==num)
        {
            pop(node->left,num);
            pop(node->right,num);
            free(node);
            node=NULL;
        }
        else
        {
            if(num> node->num)
                pop(node->right,num);
            else if (num< node->num)
                pop(node->left,num);
        }
    }
}
void pre(struct data *node)
{
    if(node)
    {
        printf("%d ",node->num);
        pre(node->left);
        pre(node->right);
    }
}
void main()
{
    push(&root,37);
    push(&root,20);
    push(&root,45);
    push(&root,5);
    push(&root,15);
    push(&root,40);
    push(&root,50);
    pre(root);
    pop(root,5);
    pre(root);
    getchar();
}

在使用pop之前,预功能运行良好。但在我使用pop功能之后,它就会中断。谁能知道哪里出错了?

2 个答案:

答案 0 :(得分:1)

pop中,您正在执行:node=NULL; - 但这只会影响传递给函数的指针的副本,而不会影响原始树中的指针。您的树保留指向您现在已释放的数据的指针。下次你对树做了很多事情,你会尝试取消引用那个指针,然后事情会发生变化并且变得繁荣(至少你希望他们这样做 - 更糟糕的是,有时它们似乎有效)。

解决此问题的一种方法是将双指针传递给pop

void pop(struct data **node, int num) { 

    if ((*node)->num == num)
        // ...
        free(*node);
        *node = NULL;
    }
}

现在您正在更改树中的指针,而不是更改您收到的函数的副本。

这仍然无法正常工作 - 您依赖于pop(child, num);来销毁当前节点的子树,但除非将num设置为相同的值,他们不会删除任何内容,只需沿着树向下寻找匹配num的节点。

您可能希望一个函数遍历树,找到您关心的节点,然后是第二个从指定节点开始遍历树的函数,并且(无条件地)销毁该节点及其子树。

答案 1 :(得分:0)

你的pop功能应该是这样的:

struct data* pop(struct data *node,int num)
{
  struct data* temp=null;
if(node)
{
    if(node->num==num)
    {
      if(node->left)
        pop(node->left,node->left->num);
      if(node->right)
        pop(node->right,node->right->num);
      free(node);
    }
    else
    {
        if(num> node->num)
            temp=pop(node->right,num);
        else if (num< node->num)
            temp=pop(node->left,num);

       if(node->right==temp)
        node->right=null;
       else if(node->left==temp)
        node->left=null;
       return temp;
    }
 }
return node;
}

如果所需的节点调整为树的根,那么只要你有逻辑来使树的根与其被调用无效,这将是有效的。