C - 从单链表中删除一个元素

C - delete an element from singly linked list

我想不通问题出在哪里,

为什么 del 函数没有按预期工作?

#include<stdio.h>
#include<malloc.h>

typedef struct list List;

struct list
{
    int data;
    List* next;
};

void prl(List* head);
void ins(List** head, int value);
void del(List** head, int value);

int main()
{
    List* head = NULL;

    ins(&head, 10);
    ins(&head, 50);
    ins(&head, 20);
    ins(&head, 150);
    ins(&head, 120);

    del(&head, 150);

    prl(head);

    //freeing dynamically allocated memory for each nodes

    while(head!=NULL)
    {
        List* t = head;
        head = head->next;
        free(t);
    }

    return 0;
}

void prl(List* head)
{
    if(head == NULL)
        printf("List is empty\n");
    else
    {
        while(head != NULL)
        {
            printf("%d ", head->data);
            head = head->next;
        }
     }
}

void ins(List** head, int value)
{
    List* node = malloc(sizeof *node);

    node->data = value;
    node->next = NULL;

    node->next =*head;
    *head = node;

}


void del(List** head, int value)
{
    List* p,*q;
    p=q=*head;

    if((*head)->data == value)
    {
        *head = (*head)->next;
        free(p);
        return;
    }
    else
    {
        while(p->next != NULL)
        {
            if(p->data == value)
            {
                q->next = p->next;
                free(p);
            }
            else
            {
                q = p;
                p = p->next;
             }
        } // while loop ends

    } // outer else ends

} // del function ends

在 运行 之后,输出为空白,我认为 del 函数外部 else 循环内部(逻辑上)有问题,但是可以使用此函数删除第一个值。

我认为你没有在此处添加 return 语句:

if(p->data == value)
    {
        q->next = p->next;
        free(p);
        return;
    }

尽管我发表了评论,但我还是决定帮助你。

让我们看看这些行:

while(p->next != NULL)
{
    if(p->data == value)
    {
        q->next = p->next;
        free(p);
    }
    else
    {
        // Irrelevant...
    }
}

假设循环内的条件 p->data == value 恰好为真,那么会发生什么?你让 q->next 指向 p->next,这可能没问题,然后你继续循环而不让 p 指向其他任何地方。

当循环继续时 p 指向您刚刚调用 free 的数据,因此取消引用 p 例如p->next 在循环条件中会导致 未定义的行为.

解决方案是适当更新 pq

while(p->next != NULL) { 
  if(p->data == value) { 
    q->next = p->next; 
    free(p); 
  } else { 
    q = p->link; //here.... 
    p = p->next; 
  }
}