单链表删除函数,在C中递归

时间:2015-04-21 10:40:11

标签: c recursion linked-list

我正在尝试为c中的项目制作学生列表 程序内部的功能是3     insert =将学生插入列表     print =打印出可用的学生     delete =从列表中删除学生

我创建了程序,使用所有三个函数都可以正常工作 现在我想使用递归制作相同的列表。

我已经使print函数递归,它正在工作 现在我试图使删除功能以相同的方式工作 不幸的是我没能使它工作

在下面的代码中,如果你运行它,你会看到它只有在你没有尝试删除列表中的最后一个节点并且你没有告诉它删除它不存在的节点时才有效。

    #include <stdio.h>
    #include <stdlib.h>

    typedef struct tf *tp;
            struct tf{
            int am;
            double gr;
            tp next;
            };

        tp head, tail, temp, aux;

    void insert1 (tp *h, tp t);
    void print1(tp h);
    void delete1(tp *h,int da);



    int main()
    {
        char fry, fry2;
        int am;
        fry = 'a';
        head = NULL;
        tail = NULL;

        while (fry != 'q')
        {
            printf("\n character given is %c\n", fry);
            if (fry != 'q')
            {
                printf("new choice\n");
                fry = 'a';
                fflush(stdin);
                fry = getchar();
                getchar();
                if (fry == 'q')
                    printf("quit\n");
                if (fry == 'i')
                {
                    fry2 = fry;
                    printf(" insert new student number am\n");
                    insert1(&head,tail);
                    fry = fry2;
                }
                if (fry == 'd')
                    {printf(" delete \n");
                    printf(" am number of student to be deleted\n");
                    scanf("%d", &am);
                    delete1(&head,am);
                    }

                if (fry == 'p')
                {
                    printf("\n printing\n");
                    print1(head);
                }
            }
        }
    }

    void insert1 (tp *h, tp t)
    {
        tp te, a;
        int da;
            te = (tp)malloc(sizeof(struct tf));
            printf(" am number for the new insert\n");
            scanf("%d", &da);
            getchar();
            te->am = da;
            te->next = NULL;
                printf("am number is %d",te->am);
                if ((*h != NULL) && (te->am < (*h)->am))
                {
                    te->next = *h;
                    *h = te;
                }

             if((*h != NULL) && ((*h)->next != NULL) && (te->am > (*h)->am))
             {
                 a=*h;
                 while((a->next != NULL) && (a->next->am < te->am))
                 {
                     a= a->next;
                 }
                 te->next = a->next;
                 a->next = te;
             }

             if((*h != NULL) && ((*h)->next == NULL) && (te->am > (*h)->am))
             {
                 (*h)->next = te;
             }

             if(*h == NULL)
             {
                 printf("\n head is null");
                 *h = te;
                 t = te;
             }
    }



    void print1(tp h)
    {
        tp a;
        a=h;
        if (a==NULL)
            return;
        printf("%d\n",a->am);
        print1(a->next);
    }




    void delete1(tp *h,int da)
    {
        tp a= *h,t= *h,temp = NULL;
        if ((*h) != NULL)
        {
            if ((*h)->am!=da)
            {
                if (a->next->am != da && a->next!=NULL)
                {
                    delete1(a->next,da);
                }
                else
                {
                    if (a->next==NULL)
                    {
                        printf("am not found\n");
                        return;
                    }
                    else
                    {
                        temp = a->next;
                        a->next = a->next->next;
                        free(temp);
                    }
                }
            }
            else
            {
                a = (*h);
                (*h)= (*h)->next;
                free(a);
            }
        }
        else
        {
            printf("empty list");
        }


    }

正如您所看到的,我希望删除功能通过查找给定的am号来删除节点,因此它将首先搜索列表以查找是否存在am号。

如果有人能给我一个关于如何使删除功能起作用的提示,我将不胜感激。

1 个答案:

答案 0 :(得分:0)

有几件事正在发生。这一行:

if (a->next->am != da && a->next!=NULL) ...

应该交换条件,否则您可能会先访问a->next并确认它不是NULL。辅助变量a和其他临时变量令人困惑而不是有用。

您将head作为指针传递给delete1函数,以便更新头部。但这并不仅影响头部:这会在你的迭代中增加一个间接层。

对于迭代调用,这意味着您必须将存储引用的指针的地址传递给当前节点(*h)->next。一开始,这是头部的地址。在后续迭代中,这是前一节点的next指针的地址。

也没有必要考虑各种情况。代码可以简单如下:

void delete1(tp *h, int da)
{
    if (*h != NULL) {
        if ((*h)->am == da) {
            tp next = (*h)->next;

            free(*h);
            *h = next;
            return;
        }

        delete1(&(*h)->next, da);
    }
}

递归调用发生在函数的末尾,或者它根本不会发生。这意味着您可以将代码重写为循环:

void delete1(tp *h, int da)
{
    while (*h != NULL) {
        if ((*h)->am == da) {
            tp next = (*h)->next;

            free(*h);
            *h = next;
            return;
        }

        h = &(*h)->next;
    }
}

这将为大型列表节省一些堆栈空间。您的insert1功能也可以清理和简化。