我正在尝试删除二叉树,我的程序工作如下:
(1)它读取树中要创建的节点数。
(2)它读取所有这些节点。
(3)打印由这些节点形成的树。
(4)它在终端读取要删除的节点。
直到这里一切正常但是当我尝试删除所需的节点时,它会给出分段错误错误。
注意:我必须通过引用传递root(这就是为什么我在delete_tree_node(int delete_val,node ** root)中为root保留了两个指针)。
我这样做的方法是: 我通过左右子进行递归调用函数delete_tree_node()以遍历树,直到我得到node的值等于用户想要删除的节点的值。如果我得到那个地方,那么我free()那个节点。
我实现此目的的代码是:(这会产生分段问题):
delete_tree_node(int delete_val, node **root)//two "**" because i call by reference in function call
{
node*temp1;
temp1=(*root);
if(delete_val==(*root)->freq)
{
free((*root));
temp1=temp1->left;
(*root)=temp1;
}
if(delete_val<temp1->freq)
{
delete_tree_node(delete_val,&temp1->left);
}
if(delete_val>temp1->freq)
{
delete_tree_node(delete_val,&temp1->right);
}
}
它的函数调用是:
delete_tree_node(delete_val, & head);//I give reference
有人可以帮助我知道:
(1)为什么会出现分段错误。
(2)删除所需节点的逻辑是否正确?如果没有,那么请您给我一段代码作为参考吗?
答案 0 :(得分:2)
为什么会出现分段错误?
因为在尝试访问*root
中的相同内存之前释放temp1->left
指向的内存。
让我们仔细研究一下: -
temp1 = (*root)
temp1现在保持与(* root)相同的内存地址,即两者都是指向同一地址的一些数字。为清楚起见,我们假设该数字为“6”。因此,它们都指向内存地址'6'。注意,它们不等于该地址的值,而只是指向它。
现在,free((*root));
告诉系统您正在释放(* root)指向的内存位置,在本例中为6.一旦释放内存,就会失去对该内存的访问权限。你提出请求的时间(通过temp1->left
),你会得到分段错误。
我希望澄清导致分段错误的原因。
粗略的一瞥告诉我你可以通过释放(* root)来解决这个问题。事实上,递归调用会更加清晰,因为你可以通过这个伪代码来描述: -delete left subtree
delete right subtree
delete root
我不会深入研究逻辑的正确性,因为它似乎是一个家庭作业问题,你最好自己解决这个问题。
答案 1 :(得分:1)
您无法释放节点然后访问它。尝试在temp1=temp1->left
之后移动免费。
此外,您必须在找到正确的节点或路径后返回(或使用其他方式):
delete_tree_node(int delete_val, node **root)
{
node *temp1;
temp1 = *root;
if(delete_val == temp1->freq)
{
temp1 = temp1->left;
free(*root);
*root = temp1;
}
else if(delete_val < temp1->freq)
{
delete_tree_node(delete_val, &temp1->left);
}
else if(delete_val > temp1->freq)
{
delete_tree_node(delete_val, &temp1->right);
}
}
答案 2 :(得分:1)
temp1=(*root); // copying the memory address of node to temp1
free((*root)); // your freeing the memory here of the node
temp1=temp1->left; // the memory your accessing is already free'd hence segmentation fault occurs
尝试交换这两个陈述。
temp1=temp1->left;
free((*root));
关于逻辑check here
的参考