【问题标题】:Single linked list delete function with recursion in CC中具有递归的单链表删除函数
【发布时间】:2015-04-21 10:40:11
【问题描述】:

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

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

我已经使打印函数递归并且它正在工作 现在我正在尝试使删除功能以相同的方式工作 不幸的是,我无法让它工作

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

    #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 编号是否存在。

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

【问题讨论】:

    标签: c recursion linked-list


    【解决方案1】:

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

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

    应该交换条件,否则您可能会访问a-&gt;next 而没有首先验证它不是NULL。辅助变量 a 和其他临时变量令人困惑而不是有用。

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

    对于您的迭代调用,这意味着您必须传递存储对当前节点的引用的指针的地址(*h)-&gt;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 函数也可以被清理和简化。

    【讨论】:

    • 非常感谢您的回复,我是初学者,我正在从错误中吸取教训,您的代码非常漂亮,我也会尝试简化插入,谢谢您的指示:D
    猜你喜欢
    • 2020-05-14
    • 2023-03-26
    • 2021-12-20
    • 2020-07-10
    • 1970-01-01
    • 1970-01-01
    • 2021-05-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多