我想制作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功能之后,它就会中断。谁能知道哪里出错了?
答案 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;
}
如果所需的节点调整为树的根,那么只要你有逻辑来使树的根与其被调用无效,这将是有效的。