Проблема заключается в первом узле, который вы инициализируете:
struct node *head = NULL;
...
for (i = 0; i < n; i++) {
...
temp->next = head;
Таким образом, tmp->next == NULL
на первой итерации оставляет head->next == NULL
. Это не будет работать для кругового списка. При попытке вставить второй узел:
p = head;
while (p->next != NULL) {
Что снова было 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_circular_fix
0-> 1-> 2-> 3-> 4->
iterate from mid-list
2-> 3-> 4-> 0-> 1->
Наконец, вы не умножаете тип node
на head
в struct node * head = NULL;
. Запишите его как 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');
}
person
David C. Rankin
schedule
18.04.2021
temp->next = head;
Какова ее цель? (Это приводит к бесконечному зацикливаниюwhile (p->next != NULL) {
.) - person chux - Reinstate Monica   schedule 18.04.2021while (p->next != NULL)
в циклическом списке --- указатель last node->next указывает на головной узел (отсюда циклический список) - person David C. Rankin   schedule 18.04.2021