C 循环链表在显示时崩溃

C 循环链表在显示时崩溃,c,data-structures,linked-list,circular-list,C,Data Structures,Linked List,Circular List,我想做一个循环链表。当我试图在创建列表后显示它时,程序不断崩溃。这是我的密码: #include <stdio.h> #include <stdlib.h> typedef struct node { int data; struct node * next; } node; node * createList(int); void display(node * head); int main() { struct node * head;

我想做一个循环链表。当我试图在创建列表后显示它时,程序不断崩溃。这是我的密码:

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

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

node * createList(int);
void display(node * head);

int main() {
    struct node * head;

    head = createList(5);
    display(head);

}

node * createList(int n) {

    int i = 0,data = 0;
    struct node * head = NULL;
    struct node * temp = NULL;
    struct node * p = NULL;

    for (i = 0; i < n; i++) {
        temp = (node*)malloc(sizeof(node));
        temp->data = data++;
        temp->next = head;

        if (head == NULL) {
            head = temp;
        } else {
            p = head;
            while (p->next != NULL) {
                p = p->next;
            }
            p->next = temp;
        }
    }
    return head;
}

void display(node * head) {
    struct node * temp = head->next;
    while (temp != head) {
        printf("%d-> \t",temp->data);
        temp = temp->next;
    }
    printf("\n");
}
#包括
#包括
类型定义结构节点{
int数据;
结构节点*下一步;
}节点;
节点*createList(int);
无效显示(节点*头部);
int main(){
结构节点*头部;
head=createList(5);
显示器(头部);
}
节点*createList(int n){
int i=0,data=0;
结构节点*head=NULL;
结构节点*temp=NULL;
结构节点*p=NULL;
对于(i=0;i数据=数据++;
温度->下一步=头部;
if(head==NULL){
压头=温度;
}否则{
p=水头;
while(p->next!=NULL){
p=p->next;
}
p->next=温度;
}
}
回流头;
}
无效显示(节点*头部){
结构节点*temp=head->next;
while(温度!=头部){
printf(“%d->\t”,临时->数据);
温度=温度->下一步;
}
printf(“\n”);
}
我做错了什么

  • 您已在
    temp->next=head中将每个
    temp
    next
    设置为
    head
    但是做得太早了(第一个只是
    NULL
    )。然后您在
    中对
    p->next
    NULL
    进行了测试,而(p->next!=NULL){
    但是您应该针对
    head
    进行测试。或者,您可以继续针对
    NULL
    进行测试,但是您需要将
    temp->next
    初始化为
    NULL
    ,并仅在for循环之后将
    head
    分配给
    temp->next

  • 显示代码从第二个链接开始

  • 下面是使用上面
    1中的第一个选项的固定代码。

        for (i = 0; i < n; i++) {
            temp = (node*)malloc(sizeof(node));
            temp->data = data++;
    
            if (head == NULL) {
                head = temp;
            } else {
                p = head;
                while (p->next != head) {
                    p = p->next;
                }
                p->next = temp;
            }
            temp->next = head;
        }
    
    但实际上,没有必要在每一个创造物上都从头开始“走”。你只需保留上一个创造物并将其链接到下一个创造物:

        for (i = 0; i < n; i++) {
            temp = (node*)malloc(sizeof(node));
            temp->data = data++;
    
            if (head == NULL) {
                head = p = temp;
            } else {
                p = p->next = temp;
            }
        }
        if (temp != NULL) {
            temp->next = head;
        }
    
    

    问题出现在您初始化的第一个节点上:

        struct node *head = NULL;
        ...
        for (i = 0; i < n; i++) {
            ...
            temp->next = head;
    
    什么是
    head->next
    再次??(哦,
    NULL
    )解除对
    NULL
    指针的引用(BOOM Segfault!)

    正确执行循环列表。插入第一个节点集时:

            if (head == NULL) {
                head = temp;
                head->next = temp;              /* you must set head->next to temp */
            } ...
    
    因此,在插入其余节点时,您只需:

            } else {
                p = head;
                while (p->next != head) {       /* iterate to last node */
                    p = p->next;
                }
                p->next = temp;                 /* now set p->next = temp */
            }
    
    现在,以相同的方式处理
    display()
    函数,例如:

    void display (node *head)
    {
        if (!head) {                            /* validate list not empty */
            puts ("(list-empty)");
            return;
        }
        
        struct node *temp = head;
        
        do {                                    /* same loop problem fixed in display() */
            printf ("%d-> \t", temp->data);
            temp = temp->next;
        } while (temp != head);
        
        putchar ('\n');
    }
    
    如果进行了更改,则可以使用以下工具测试列表:

    int main (void) {
        struct node *head, *tmp;
    
        head = createList(5);
        display (head);
    
        puts ("\niterate from mid-list");
        tmp = head;
        tmp = tmp->next;
        tmp = tmp->next;
        display (tmp);
    }
    
    示例使用/输出

    $。/bin/lls\u循环\u修复
    0->     1->     2->     3->     4->
    从中间列表迭代
    2->     3->     4->     0->     1->
    
    最后,在
    struct node*head=NULL;
    中,将类型
    node
    乘以
    head
    ;将其写为
    struct node*head=NULL;
    (对于所有函数声明也是如此)可读性更强

    当您要从列表中删除注释时,必须为
    head
    tail
    (最后一个节点)创建一个特例。从这个意义上说,由于没有
    prev
    节点指针来跟踪前一个节点,单链接列表比双链接列表要花费更多的精力

    仔细检查一下,如果有问题请告诉我

    一个完整的例子是:

    #include <stdio.h>
    #include <stdlib.h>
    
    typedef struct node {
        int data;
        struct node *next;
    } node;
    
    node *createList (int);
    void display (node *head);
    
    int main (void) {
        struct node *head, *tmp;
    
        head = createList(5);
        display (head);
    
        puts ("\niterate from mid-list");
        tmp = head;
        tmp = tmp->next;
        tmp = tmp->next;
        display (tmp);
    }
    
    node *createList (int n)
    {
        int i = 0,data = 0;
        struct node *head = NULL;
        struct node *temp = NULL;
        struct node *p = NULL;
    
        for (i = 0; i < n; i++) {
            if (!(temp = malloc (sizeof *temp))) {
                perror ("malloc-temp");
                return NULL;
            }
            temp->data = data++;
            temp->next = head;                  /* head is NULL on 1st node insertion */
    
            if (head == NULL) {
                head = temp;
                head->next = temp;              /* you must set head->next to temp */
            } else {
                p = head;
                while (p->next != head) {       /* iterate to last node */
                    p = p->next;
                }
                p->next = temp;                 /* now set p->next = temp */
            }
        }
        return head;
    }
    
    void display (node *head)
    {
        if (!head) {                            /* validate list not empty */
            puts ("(list-empty)");
            return;
        }
        
        struct node *temp = head;
        
        do {                                    /* same loop problem fixed in display() */
            printf ("%d-> \t", temp->data);
            temp = temp->next;
        } while (temp != head);
        
        putchar ('\n');
    }
    
    #包括
    #包括
    类型定义结构节点{
    int数据;
    结构节点*下一步;
    }节点;
    节点*createList(int);
    无效显示(节点*头部);
    内部主(空){
    结构节点*head,*tmp;
    head=createList(5);
    显示器(头部);
    puts(“\n从中间列表中删除”);
    tmp=头部;
    tmp=tmp->next;
    tmp=tmp->next;
    显示器(tmp);
    }
    节点*createList(int n)
    {
    int i=0,data=0;
    结构节点*head=NULL;
    结构节点*temp=NULL;
    结构节点*p=NULL;
    对于(i=0;i数据=数据++;
    temp->next=head;/*第一次插入节点时head为空*/
    if(head==NULL){
    压头=温度;
    head->next=temp;/*必须将head->next设置为temp*/
    }否则{
    p=水头;
    而(p->next!=head){/*迭代到最后一个节点*/
    p=p->next;
    }
    p->next=temp;/*现在设置p->next=temp*/
    }
    }
    回流头;
    }
    无效显示(节点*头部)
    {
    如果(!head){/*验证列表不为空*/
    puts(“(列表为空)”);
    返回;
    }
    结构节点*温度=头部;
    是否在display()中修复了{/*相同的循环问题*/
    printf(“%d->\t”,临时->数据);
    温度=温度->下一步;
    }while(temp!=头部);
    putchar('\n');
    }
    
    提示:解释这行代码:
    temp->next=head;
    它的目标是什么?(它导致
    while(p->next!=NULL){
    永远循环。)循环列表中不会有
    while(p->next!=NULL)
    ——最后一个节点->下一个指针指向head节点(因此是循环列表)谢谢你的回复,我已经尝试了你的代码,但它仍然在崩溃:/@VenoM我还将
    temp->next
    初始化为
    NULL
    ,现在就试试吧,添加temp->next=NULL成功了,谢谢!
    void display (node *head)
    {
        if (!head) {                            /* validate list not empty */
            puts ("(list-empty)");
            return;
        }
        
        struct node *temp = head;
        
        do {                                    /* same loop problem fixed in display() */
            printf ("%d-> \t", temp->data);
            temp = temp->next;
        } while (temp != head);
        
        putchar ('\n');
    }
    
    int main (void) {
        struct node *head, *tmp;
    
        head = createList(5);
        display (head);
    
        puts ("\niterate from mid-list");
        tmp = head;
        tmp = tmp->next;
        tmp = tmp->next;
        display (tmp);
    }
    
    #include <stdio.h>
    #include <stdlib.h>
    
    typedef struct node {
        int data;
        struct node *next;
    } node;
    
    node *createList (int);
    void display (node *head);
    
    int main (void) {
        struct node *head, *tmp;
    
        head = createList(5);
        display (head);
    
        puts ("\niterate from mid-list");
        tmp = head;
        tmp = tmp->next;
        tmp = tmp->next;
        display (tmp);
    }
    
    node *createList (int n)
    {
        int i = 0,data = 0;
        struct node *head = NULL;
        struct node *temp = NULL;
        struct node *p = NULL;
    
        for (i = 0; i < n; i++) {
            if (!(temp = malloc (sizeof *temp))) {
                perror ("malloc-temp");
                return NULL;
            }
            temp->data = data++;
            temp->next = head;                  /* head is NULL on 1st node insertion */
    
            if (head == NULL) {
                head = temp;
                head->next = temp;              /* you must set head->next to temp */
            } else {
                p = head;
                while (p->next != head) {       /* iterate to last node */
                    p = p->next;
                }
                p->next = temp;                 /* now set p->next = temp */
            }
        }
        return head;
    }
    
    void display (node *head)
    {
        if (!head) {                            /* validate list not empty */
            puts ("(list-empty)");
            return;
        }
        
        struct node *temp = head;
        
        do {                                    /* same loop problem fixed in display() */
            printf ("%d-> \t", temp->data);
            temp = temp->next;
        } while (temp != head);
        
        putchar ('\n');
    }