C 二元搜索树只包含根,删除会导致打印无限多个地址
此代码:C 二元搜索树只包含根,删除会导致打印无限多个地址,c,pointers,binary-search-tree,C,Pointers,Binary Search Tree,此代码: 插入 搜查 打印各种遍历 删除 删除是问题所在,我自己编写了这段代码(因此这可能不是常规方法)。我将删除分为三个部分进行检查: 如果目标节点具有两个子节点 如果目标节点有一个子节点 如果目标节点没有子节点 这个程序的每一部分都正确地运行,正确的输出(只是所有的!),除了根节点是剩下的唯一节点,我们正试图删除根节点 它进入nonode函数(在函数中有根的特殊情况),甚至打印“您已经删除了内存中唯一的节点”。再次给出所有选项。但是,如果在此之后选择任何选项,则会显示错误。例如,在尝试打印各
#包括
#包括
结构体
{
结构bt*左;
int数据;
结构bt*对;
};
结构bt*root=NULL,**sp=NULL;
无效插入(结构bt**,int);
void prtraversal(结构bt**);
体内空洞(结构bt**);
potraversal无效(结构bt**);
无效搜索(结构bt**,int);
void del(结构bt**n,整数键);
无效非节点(结构bt**n);
void onenode(结构bt**n);
void bothnode(结构bt**n);
main()
{
int-ch,键;
printf(“******\n\n程序自动避免包含重复编号\n\n**********”;
而(1)
{
printf(“\n输入您的选择\n1用于插入\n2用于搜索\n3用于各种遍历\n4用于删除\n5用于退出\n”);
scanf(“%d”和“ch”);
开关(ch)
{
案例1:
printf(“输入插入密钥\n”);
scanf(“%d”和键)(&key);
插入(&根,键);
打破
案例2:
if(root!=NULL)
{
printf(“输入您的搜索密钥\n”);
scanf(“%d”和键)(&key);
搜索(&根,键);
}
其他的
{
printf(“\n内存中没有二叉树\n”);
}
打破
案例3:
if(root!=NULL)
{
printf(“\n\n优先级遍历:”);
pr遍历(&根);
printf(“\n\n顺序遍历:”);
血管内(&根);
printf(“\n\n存储程序遍历:”);
potraversal(&根);
}
其他的
{
printf(“\n内存中没有二叉树\n”);
}
打破
案例4:
if(root!=NULL)
{
printf(“输入要删除的密钥\n”);
scanf(“%d”和键)(&key);
del(&根,键);
}
其他的
{
printf(“\n内存中没有二叉树\n”);
}
打破
案例5:
出口(1);
违约:
printf(“\n错误选择\n”);
}
sp=NULL;
}
}
void del(结构bt**n,整数键)
{
如果((*n)!=NULL)
{
如果(关键数据)
del(&((*n)->左),键;
否则如果(键>(*n)->数据)
del(&((*n)->右),键;
else if(key==(*n)->数据)
{
printf(“\n找到元素\n”);
printf(“\n正在删除\n”);
sp=n;
如果((*n)->右)!=NULL&(*n)->左)!=NULL)
{
节点(&((*n)->左);
}
如果((*n)->右)!=NULL&(*n)->左)==NULL,则为else
{
单极(&(*n)->右);
}
如果((*n)->左)!=NULL&(*n)->右)==NULL,则为else
{
单极(&((*n)->左);
}
如果((*n)->左)==NULL&(*n)->右)==NULL,则为else
{
非节点(&根);
}
}
}
其他的
{
printf(“\n未找到元素\n”);
}
}
void nonode(struct bt**n)//删除没有任何子节点的目标节点,根地址提供给struct bt**n
{
struct bt**parent=n;//存储目标节点之前的节点地址,将在此函数中更新
if(sp!=&root)//从上一个函数存储在sp中的目标节点地址
{
while((*n)->data!=(*sp)->data)//查找目标节点之前的节点地址并将其存储在struct bt**parent中
{
parent=n;//结构bt**n遍历树时频繁更新父级
如果(((*sp)->数据)数据)
n=&(*n)->左;
如果(((*sp)->数据)>((*n)->数据))
n=&(*n)->右;
}
if((*parent)->right==(*sp))//检查父节点的右侧是否包含目标节点的地址
{
(*父级)->right=NULL;
免费(*sp);
}
else if((*parent)->left==(*n))//else检查父节点的左侧是否包含目标节点的地址
{
(*父项)->left=NULL;
免费(*n);
}
}
else if(sp==&root)//如果必须删除根节点,则两边都没有子节点,树中只有一个节点
{
免费(*sp);
printf(“\n您删除了内存中唯一的节点\n”);
}
}
删除后忘记将根目录设置为空:
else if(sp==&root)
{
free(*sp);
*sp = NULL; // <-- add this line
printf("\nYOU DELETED THE ONLY NODE IN MEMORY\n");
}
else if(sp==&root)
{
免费(*sp);
*sp=NULL;//从树中删除单个节点时,您没有将root
设置为NULL。因为root是全局的,所以您可以在del(struct bt**n,int key)
中将其设置为NULL。当您进行此检查时:
else if(((*n)->left)==NULL && ((*n)->right)==NULL)
您已经知道要删除根节点,因为前面的条件已经用尽了所有其他可能性。因此,您只需释放根节点并将其设置为NULL即可
else
{
free(*n);
*n = NULL;
}
另一方面,您的删除算法非常复杂
else
{
free(*n);
*n = NULL;
}
void wrap_del(strut tree ** t)
{
del(*t);
*t = NULL;
}
void del(struct tree * t)
{
if (*t == NULL)
return; //called on a null ptr
del(t->left);
del(t->right);
free(t);
}
else if(((*n)->left)==NULL && ((*n)->right)==NULL)
{
nonode(&root);
}
else nonode(n);
else
{
free(*n);
*n = NULL;
}