C 这段代码有什么问题?

C 这段代码有什么问题?,c,data-structures,linked-list,segmentation-fault,doubly-linked-list,C,Data Structures,Linked List,Segmentation Fault,Doubly Linked List,我写的是删除双链接列表的最后一个节点。但是,每次当列表中有2个或2个以上元素时,此函数都会给我分段错误 void deleteEnd() { struct node *ptr; if(head==NULL) printf("\nList is empty.First add some numbers"); else if(head->next==NULL) { head = NULL; fr

我写的是删除双链接列表的最后一个节点。但是,每次当列表中有2个或2个以上元素时,此函数都会给我分段错误

void deleteEnd()
{
    struct node *ptr;
    if(head==NULL)
        printf("\nList is empty.First add some numbers");
    else if(head->next==NULL)
    {
        head = NULL;
        free(head);
    }
    else
    {
        ptr = head;   
        while(ptr->next != NULL)  
        {  
            ptr = ptr -> next;   
        }  
        ptr -> prev -> next = NULL;   
        free(ptr);  
    }
}

通常,从链表中删除节点时,最好将对列表第一个节点的引用作为函数的参数传递。在你的情况下,你没有告诉我们头部来自哪里,我认为这可能是一个非常有用的信息,我打赌错误隐藏在那里

这就是实现的样子:

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

struct node
{
    int data;
    struct node *next;
};

// insert end node: this is for testing purposes
struct node *insertEnd(struct node *head, int value) {
    struct node *ptr, *new_node;
    ptr = head;

    new_node = (struct node *) malloc(sizeof(struct node));
    new_node->data = value;
    new_node->next = NULL;

    // The list is empty
    if (head == NULL) {
        head = new_node;
        return head;
    }
    // Non empty list
    while (ptr->next != NULL) {
        ptr = ptr->next;
    }
    ptr->next = new_node;
    return head;
}

// delete end node
struct node *deleteEnd(struct node *head) {
    struct node *ptr, *preptr;
    ptr = head;
    preptr = NULL;
    // The list is empty
    if (head == NULL) {
        printf("The list is empty. Nothing to delete.\n");
        return head;
    }
    while(ptr->next != NULL) {
        preptr = ptr;
        ptr= ptr->next;
    }
    free(ptr);
    if (preptr == NULL) {
        head = NULL;
    }
    else {
        preptr->next = NULL;
    }
    return head;
}

int main(void) {
    struct node *llist;
    llist = NULL;

    llist = insertEnd(llist, 10);
    llist = insertEnd(llist, 20);
    llist = insertEnd(llist, 30);

    llist = deleteEnd(llist);
    llist = deleteEnd(llist);
    llist = deleteEnd(llist);

    return 0;
}
#包括
#包括
结构节点
{
int数据;
结构节点*下一步;
};
//插入结束节点:这用于测试目的
结构节点*insertEnd(结构节点*head,int值){
结构节点*ptr,*新节点;
ptr=头部;
新节点=(结构节点*)malloc(sizeof(结构节点));
新建_节点->数据=值;
新建节点->下一步=空;
//列表是空的
if(head==NULL){
head=新的_节点;
回流头;
}
//非空列表
while(ptr->next!=NULL){
ptr=ptr->next;
}
ptr->next=新建_节点;
回流头;
}
//删除结束节点
结构节点*删除端(结构节点*头){
结构节点*ptr,*preptr;
ptr=头部;
preptr=NULL;
//列表是空的
if(head==NULL){
printf(“列表为空,无需删除。\n”);
回流头;
}
while(ptr->next!=NULL){
preptr=ptr;
ptr=ptr->next;
}
免费(ptr);
if(preptr==NULL){
head=NULL;
}
否则{
preptr->next=NULL;
}
回流头;
}
内部主(空){
结构节点*llist;
llist=NULL;
llist=插入(llist,10);
llist=插入(llist,20);
llist=插入(llist,30);
llist=deleteEnd(llist);
llist=deleteEnd(llist);
llist=deleteEnd(llist);
返回0;
}

维护一个全局变量头并在每次推/弹出后更新它总是一个好主意。见此:

struct node
{
    int data;
    struct node *next;
};

struct node *start = NULL;

struct node *deleteEnd(struct node *start)
{
    struct node *ptr = start;
    if(ptr==NULL)
    {
        printf("\nList is empty!!!");
        return start;
    }
    else if(ptr->next == NULL)
    {
        free(ptr);
        start = NULL;
        return start;        
    }
    else
    {
        while((ptr->next)->next!=NULL)      //by doing this you dont have to maintain a prev pointer
        {
            ptr=ptr->next;
        }
        struct node *temp = ptr->next;
        free(temp);
        ptr->next = NULL;
        return start;
              
    }

}

希望这有帮助

在空指针上使用
free
是有效的,但它完全没有任何作用。如果列表中只剩下一个节点(
head
),请提供一个
else。在调用
free()
之前,您
NULL
ing
head
正在泄漏内存。因为你的例子不完整,所以在这一点上不能说更多。我怀疑向列表中添加元素的代码没有正确初始化
prev
/
next
,但这是猜测。