链表删除问题,代码有问题,求解

下图是问题:

img


解答如图问题时,发现删除操作有问题,不出结果,直到其中两个条件语句(已在代码中标出)交换位置后,可以得到正确结果,不知道为什么,特来请教。
以下是图中问题解决代码。


//这个是有问题的代码
#include<stdio.h>
#include<stdlib.h>
typedef struct node {
    int data;
    struct node *next;
} Node, *LinkList;
LinkList Listinit() {
    Node *L;
    L = (Node*)malloc(sizeof(Node));
    if (L == NULL)exit(0);
    L->next = NULL;
    return L;
}
LinkList creat(int n) {
    Node *L;
    int x;
    L = (Node*)malloc(sizeof(Node));
    L->next = NULL;
    Node *r;
    r = L;
    while (n--) {
        scanf("%d", &x);
        Node *p;
        p = (Node*)malloc(sizeof(Node));
        p->data = x;
        r->next = p;
        r = p;
    }
    r->next = NULL;
    return L;
}
LinkList delet(Node *L, int x) {
    Node *p, *pre;
    p = L->next;
    while (p->next) {
        //以下代码与另一个有所不同
        if (p->data == x) {
            pre->next = p->next;
            free(p);
        }
        if (p->data != x) {
            while (p->data != x && p->next) {
                pre = p;
                p = p->next;
            }
        }
        //以上代码与另一个有所不同
        p = pre->next;
    }
    return L;
}
void print(Node *L) {
    Node *p = L->next;
    while (p) {
        printf("%d ", p->data);
        p = p->next;
    }
}
int main() {
    Node *L;
    int x, n;
    scanf("%d", &n);
    L = Listinit();
    L = creat(n);
    scanf("%d", &x);
    L = delet(L, x);
    print(L);
    return 0;
}


//这个是没有问题的代码
#include<stdio.h>
#include<stdlib.h>
typedef struct node {
    int data;
    struct node *next;
} Node, *LinkList;
LinkList Listinit() {
    Node *L;
    L = (Node*)malloc(sizeof(Node));
    if (L == NULL)exit(0);
    L->next = NULL;
    return L;
}
LinkList creat(int n) {
    Node *L;
    int x;
    L = (Node*)malloc(sizeof(Node));
    L->next = NULL;
    Node *r;
    r = L;
    while (n--) {
        scanf("%d", &x);
        Node *p;
        p = (Node*)malloc(sizeof(Node));
        p->data = x;
        r->next = p;
        r = p;
    }
    r->next = NULL;
    return L;
}
LinkList delet(Node *L, int x) {
    Node *p, *pre;
    p = L->next;
    while (p->next) {
        //以下代码与另一个有所不同 
        if (p->data != x) {
            while (p->data != x && p->next) {
                pre = p;
                p = p->next;
            }
        }
        if (p->data == x) {
            pre->next = p->next;
            free(p);
        }
        //以上代码与另一个有所不同 
        p = pre->next; 
    }
    return L;
}
void print(Node *L) {
    Node *p = L->next;
    while (p) {
        printf("%d ", p->data);
        p = p->next;
    }
}
int main() {
    Node *L;
    int x, n;
    scanf("%d", &n);
    L = Listinit();
    L = creat(n);
    scanf("%d", &x);
    L = delet(L, x);
    print(L);
    return 0;
}

想了很久没找到答案,很想知道为什么,希望知道原因的朋友不吝评论,感谢。

因为交换顺序之前,你第一个if里面可能会释放p的内存,所以第二个if就没法使用p,解决办法:

  • 1.像你现在这样,交换顺序
  • 2.将原来的第二个if改成else if,改了以后,如果执行了if,就不会执行else if了

img

listinit是多余的函数,根本没有实际用到。del函数里面,两个while也没有必要,影响美观。

LinkList delet(Node *L, int x) {
    Node *p, *pre;
    p = L;
    while (p->next!=null) {
        if (p->next->data == x) {
            pre=p->next;
            p->next=pre->next;
            delete(pre);
            
            break;
        }
        p = p->next;
    }
}