C 二元搜索树只包含根,删除会导致打印无限多个地址

C 二元搜索树只包含根,删除会导致打印无限多个地址,c,pointers,binary-search-tree,C,Pointers,Binary Search Tree,此代码: 插入 搜查 打印各种遍历 删除 删除是问题所在,我自己编写了这段代码(因此这可能不是常规方法)。我将删除分为三个部分进行检查: 如果目标节点具有两个子节点 如果目标节点有一个子节点 如果目标节点没有子节点 这个程序的每一部分都正确地运行,正确的输出(只是所有的!),除了根节点是剩下的唯一节点,我们正试图删除根节点 它进入nonode函数(在函数中有根的特殊情况),甚至打印“您已经删除了内存中唯一的节点”。再次给出所有选项。但是,如果在此之后选择任何选项,则会显示错误。例如,在尝试打印各

此代码:

  • 插入
  • 搜查
  • 打印各种遍历
  • 删除
  • 删除是问题所在,我自己编写了这段代码(因此这可能不是常规方法)。我将删除分为三个部分进行检查:

  • 如果目标节点具有两个子节点
  • 如果目标节点有一个子节点
  • 如果目标节点没有子节点
  • 这个程序的每一部分都正确地运行,正确的输出(只是所有的!),除了根节点是剩下的唯一节点,我们正试图删除根节点

    它进入nonode函数(在函数中有根的特殊情况),甚至打印“您已经删除了内存中唯一的节点”。再次给出所有选项。但是,如果在此之后选择任何选项,则会显示错误。例如,在尝试打印各种遍历时,它会在检查遍历时打印一个无限的地址列表,最终,.exe文件会停止,而不是打印“内存中没有二叉树”

    #包括
    #包括
    结构体
    {
    结构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;
    }