1

我想做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 之前,Pre 函数运行良好。但是在我使用 pop 功能之后,它就中断了。谁能知道错误在哪里?

4

2 回答 2

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

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

于 2012-06-10T06:57:43.710 回答
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;
}

只要您有逻辑从调用它的位置取消树的根,如果所需的节点调整为树的根,这将起作用。

于 2012-06-10T08:44:50.617 回答