kokusen 2023-06-23 22:32 采纳率: 0%
浏览 48

为什么我写的con( )函数第二次调用就会死循环,第一次却没事?

谁能帮忙看看为什么我写的con( )函数第二次调用就会死循环?第二次运行的过程中卡死在sort( )函数中的while语句中:

Lnode* sort(Lnode* L)    
{
    Lnode *tail, *ml, *m, *q;
    m = L;
    if (m != NULL){
        while (m->next != NULL)      //逐句检查的时候,发现第二次调用con(  )时,
            m = m->next;                //con(  )运行到sort函数时一直卡在这两句循环,但是第一次调用con( )却不会这样
    }

以下是全代码(一元稀疏多项式计算器)


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

typedef struct node
{
    float c;    //系数
    int e;        //指数
    int n;        //项数
    struct node* next;
}Lnode;

Lnode* creat(int n)
{
    Lnode* L;
    Lnode* tail;
    tail = L = NULL;
    for (int i = 0; i < n; i++) {    //尾插法记录多项式数据
        Lnode* p;
        p = (Lnode*)malloc(sizeof(Lnode));
        p->next = NULL;
        printf("请分别输入第%d项的系数和指数:", i + 1);
        scanf("%f %d", &p->c, &p->e);
        if (i == 0) {
            L = p;
            tail = p;
        }
        else {
            tail->next = p;
            tail = p;
        }
    }
    L->n = n;
    Lnode* sort(Lnode * L);
    sort(L);
    return L;
}
void swap(Lnode* p,Lnode* q)    //交换操作
{
    float temp_c;
    int temp_e;
    temp_c = p->c; p->c = q->c; q->c = temp_c;
    temp_e = p->e; p->e = q->e; q->e = temp_e;
}
Lnode* sort(Lnode* L)        //降序冒泡排序
{
    Lnode *tail, *ml, *m, *q;
    m = L;
    if (m != NULL){
        while (m->next != NULL)
            m = m->next;
    }
    tail = m;
    while (tail != L){ 
        ml = L;        //ml指向最后一次交换的位置
        for (m = L; m != tail; m = m->next){
            q = m->next;
            if (m->e < q->e){
                swap(m, q);
                ml = m;
            }
        }
        tail = ml;
    }
    return m;
}

void disp(Lnode* L,int n)
{
    Lnode* p;
    p = L;
    if (p == NULL)
        printf("0\n\n");
    else{
        while (p != NULL) {
            printf("%.2fX^%d ", p->c, p->e);
            if (p->next != NULL) {
                if ((p->next)->c >= 0)
                    printf("+");
            }
            p = p->next;
        }
        printf("\n");
        p = L;
        printf("序列形式:(%d, ", n);
        while (p != NULL) {
            printf("%.2f,%d", p->c, p->e);
            if (p->next != NULL)
                printf(", ");
            p = p->next;
        }
        printf(")");
        printf("\n\n");
    }
}
void calculate(Lnode* L)
{
    Lnode* p = L;
    int x;
    double sum = 0;
    printf("请输入X的值:");
    scanf("%d", &x);
    while (p != NULL)
    {
        sum += p->c * pow(x, p->e);
        p = p->next;
    }
    printf("当X的值为%d时,多项式的值为:%.2f\n\n", x, sum);
}
Lnode* con(Lnode* a, Lnode* b, int m)    //多项式a、b求和差
{
    Lnode* p, * q, *tail;
    p = a;  q = b;  tail = p; 
    if (m == 4) {
        Lnode* qi = q;
        while (qi != NULL) {
            qi->c = -qi->c;
            qi = qi->next;
        }
    }
    if (p != NULL) {
        while (tail->next != NULL)
            tail = tail->next;
        tail->next = q;
        p = sort(p);
        p->n += q->n;
    }
    if (p == NULL && q != NULL)
        p = q;
    tail = p;
    while (tail != NULL){        //合并同类项
        if(tail->next != NULL){
            if (tail->e == (tail->next)->e) {
                Lnode* r = tail->next;
                tail->c += r->c;
                tail->next = r->next;
                free(r);
                p->n -= 1;
            }
        }
        tail = tail->next;
    }
    return p;
    free(p);
}
void select(Lnode* a, Lnode* b)
{
    Lnode* c = NULL; Lnode* d = NULL;
    int m;
    printf("请输入数字指令:(0:退出计算器  1:计算a在X处的值  2:计算b在X处的值  3:求a+b  4:求a-b  5:计算a+b在X处的值  6:计算a-b在X处的值)\n");
    scanf("%d",&m);
    while (m != 0){
        switch (m) {
        case 1:
            calculate(a);
            printf("请输入下一个数字指令...\n");
            scanf("%d", &m);
            break;
        case 2:
            calculate(b);
            printf("请输入下一个数字指令...\n");
            scanf("%d", &m);
            break;
        case 3:
            c = con(a, b, 3);
            printf("\n多项式 a+b = ");
            disp(c, c->n);
            //free(c);
            printf("请输入下一个数字指令...\n");
            scanf("%d", &m);
            break;
        case 4:
            d = con(a, b, 4);
            printf("\n多项式 a-b = ");
            disp(d, d->n);
            printf("请输入下一个数字指令...\n");
            scanf("%d", &m);
            break;
        case 5:
            if (c == NULL){
                c = con(a, b, 3);
                printf("\n多项式 a+b = ");
                disp(c, c->n);
            }
            calculate(c);
            printf("请输入下一个数字指令...\n");
            scanf("%d", &m);
            break;
        case 6:
            if (d == NULL){
                d = con(a, b, 4);
                printf("\n多项式 a+b = ");
                disp(d, d->n);
            }
            calculate(c);
            printf("请输入下一个数字指令...\n");
            scanf("%d", &m);
            break;
        default: printf("请输入正确的数字指令!\n"); break;
        }
    }
}

int main()
{
    Lnode* a, * b; Lnode *c = NULL; Lnode* d;
    int n1;
    printf("请输入多项式a的项数: ");
    scanf("%d", &n1);
    a = creat(n1);
    printf("\n多项式 a = ");
    disp(a,n1);

    int n2;
    printf("请输入多项式b的项数: ");
    scanf("%d", &n2);
    b = creat(n2);
    printf("\n多项式 b = ");
    disp(b, n2);

    c = con(a, b, 3);
    printf("\n多项式 a+b = ");
    disp(c, c->n);

    d = con(a, b, 4);
    printf("\n多项式 a-b = ");
    disp(d, d->n);

    //select(a, b);
    return 0;
}

  • 写回答

3条回答 默认 最新

  • PhoenixRiser 2023-06-23 22:42
    关注

    TechWhizKid参考GPT回答:

    • 当你执行 tail->next = q; 时,你将链表 a 的尾部连接到链表 b 的头部,而如果你在第二次调用 con() 函数时再次这样做,那么链表 a 的尾部就会再次连接到链表 b 的头部,形成了一个循环引用,也就是链表 a 和 b 共享了一部分节点。
    • 解决这个问题的一个方式是在调用 con() 函数时创建链表 a 和 b 的副本,这样就不会修改原始链表。另一个解决方案是在调用 con() 函数后不再使用原始链表,因为 con() 函数已经修改了它们。
    • con()函数在处理完两个链表后,会对这两个链表造成改变。在调用con()函数后,链表 a 和 b 不再是两个独立的链表,而是连接在一起的。这就是为什么第二次调用con()函数时,你会发现一个死循环的问题,因为你实际上已经改变了这两个链表的结构。
    • 下面将给出一种可能的解决方法,即在con()函数中创建链表 a 和 b 的副本,这样就可以对副本进行修改,而不会影响到原始的链表 a 和 b。

    修改的con()函数如下:

    Lnode* con(Lnode* a, Lnode* b, int m)    //多项式a、b求和差
    {
        Lnode* p, * q, *tail, *new_a, *new_b, *new_tail;
        
        // 创建 a 的副本
        new_a = NULL;
        new_tail = NULL;
        for(p = a; p != NULL; p = p->next) {
            Lnode* new_node = (Lnode*)malloc(sizeof(Lnode));
            new_node->c = p->c;
            new_node->e = p->e;
            new_node->next = NULL;
            if(new_a == NULL) {
                new_a = new_node;
                new_tail = new_node;
            } else {
                new_tail->next = new_node;
                new_tail = new_node;
            }
        }
    
        // 创建 b 的副本
        new_b = NULL;
        new_tail = NULL;
        for(p = b; p != NULL; p = p->next) {
            Lnode* new_node = (Lnode*)malloc(sizeof(Lnode));
            new_node->c = p->c;
            new_node->e = p->e;
            new_node->next = NULL;
            if(new_b == NULL) {
                new_b = new_node;
                new_tail = new_node;
            } else {
                new_tail->next = new_node;
                new_tail = new_node;
            }
        }
        
        p = new_a;  
        q = new_b;  
        tail = p; 
        if (m == 4) {
            Lnode* qi = q;
            while (qi != NULL) {
                qi->c = -qi->c;
                qi = qi->next;
            }
        }
        if (p != NULL) {
            while (tail->next != NULL)
                tail = tail->next;
            tail->next = q;
            p = sort(p);
            p->n += q->n;
        }
        if (p == NULL && q != NULL)
            p = q;
        tail = p;
        while (tail != NULL){        //合并同类项
            if(tail->next != NULL){
                if (tail->e == (tail->next)->e) {
                    Lnode* r = tail->next;
                    tail->c += r->c;
                    tail->next = r->next;
                    free(r);
                    p->n -= 1;
                }
            }
            tail = tail->next;
        }
        return p;
    }
    
    
    

    在这个修改过的con()函数中,先创建了链表 a 和 b 的副本,然后在副本上进行所有的操作,从而保留了原始链表的内容。这样第二次调用con()函数时,仍然用原始链表 a 和 b,因此不会出现死循环的问题。

    这里创建了新的节点,所以你要确保在不再要这些节点的时候释放它们的内存。在C语言中,如果你分配了内存,但是没有释放它,那么就会导致内存泄漏,这可能会在你的程序运行一段时间后导致问题。你可以通过调用 free() 函数来释放你分配的内存。

    评论

报告相同问题?

问题事件

  • 创建了问题 6月23日

悬赏问题

  • ¥15 刚接触VFP,我想知道为什么是这种情况,有人可以看看吗
  • ¥15 io.jsonwebtoken.security.Keys
  • ¥15 急,ubuntu安装后no caching mode page found等
  • ¥15 联想交换机NE2580O/NE1064TO安装SONIC
  • ¥15 防火墙的混合模式配置
  • ¥15 Ubuntu不小心注销了要怎么恢复啊
  • ¥15 win10电脑安装完plcsim advanced4.0运行时为什么会提示找不到虚拟网卡
  • ¥15 安装powerbuilder10卡在安装程序正在运行这个页面 没有下一步任何指令
  • ¥15 关于mpi的问题:请问遇到这种情况需要怎么解决,出现这个问题后电脑不能进行mpi多核运行只能进行单核运行
  • ¥50 微信聊天记录备份到电脑提示成功了,但还是没同步到电脑微信