I'm writing a program in C for reversing a circular singly linked list. I keep getting segmentation fault for some reason. I'm sure the problem is with the reverse
function as I tried commenting the function call, the program works fine.
For my reverse()
function, I have used 3 pointers: prev
, next
and curr
. The logic is that I'll run a loop till curr
takes the address of head
, which will be stored in the link
part of the last node since it is a circular linked list. I'll keep updating curr->link
using prev
pointer which will change its link from the next to its previous node.
When the loop breaks, head->link = prev;
and head = prev;
will update the respective addresses such that they point to the first node of the reversed list.
//reversing CLL
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *link;
} *head;
void reverse() {
struct node *prev = NULL, *curr = head, *next;
while (curr != head) {
next = curr->link;
curr->link = prev;
prev = curr;
curr = next;
}
head->link = prev;
head = prev;
}
void createList(int n) {
int i, data;
head = (struct node *)malloc(sizeof(struct node));
struct node *ptr = head, *temp;
printf("Enter data of node 1\t");
scanf("%d", &data);
head->data = data;
head->link = NULL;
for (i = 2; i <= n; i++) {
temp = (struct node *)malloc(sizeof(struct node));
printf("Enter data of node %d\t", i);
scanf("%d", &data);
temp->data = data;
temp->link = NULL;
ptr->link = temp;
ptr = ptr->link;
}
ptr->link = head;
}
void disp() {
struct node *ptr = head;
do {
printf("%d\t", ptr->data); //gdb debugger shows problem is in this line
ptr = ptr->link;
} while (ptr != head);
}
int main() {
int n;
printf("Enter no of nodes to be created\t");
scanf("%d", &n);
createList(n);
printf("\n\nList is displayed below!\n");
disp();
printf("\n\nReversing list ...\n");
reverse(); // on commenting this call, disp() function
// works accurately showing node data non-reversed
disp();
printf("\n\nList successfully reversed!\n");
}
The loop in the reverse()
function exits immediately because curr
is initialized to the value of head
so the test while (curr != head)
is false at the first iteration.
reverse()
then sets head->link
to NULL
and finally head
is also set to NULL
(the initial value of prev
), which explains the segmentation fault in the subsequent disp()
function where you use a do { } while (pre != head)
that cannot handle an empty list.
Here is a modified version:
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *link;
};
struct node *reverse(struct node *head) {
struct node *prev = NULL, *curr = head;
if (head) {
do {
struct node *next = curr->link;
curr->link = prev;
prev = curr;
curr = next;
} while (curr != head);
curr->link = prev;
head = prev;
}
return head;
}
struct node *createList(int n) {
struct node *head = NULL, *tail = NULL, *temp;
int i;
for (i = 1; i <= n; i++) {
temp = (struct node *)malloc(sizeof(struct node));
temp->data = 0;
temp->link = NULL;
printf("Enter data of node %d\t", i);
scanf("%d", &temp->data);
if (head == NULL) {
head = temp;
} else {
tail->link = temp;
}
tail = temp;
temp->link = head;
}
return head;
}
void disp(struct node *head) {
if (head) {
struct node *ptr = head;
do {
printf("%d\t", ptr->data);
ptr = ptr->link;
} while (ptr != head);
}
}
int main() {
struct node *head;
int n = 0;
printf("Enter no of nodes to be created\t");
scanf("%d", &n);
head = createList(n);
printf("\n\nList is displayed below!\n");
disp(head);
printf("\n\nReversing list ...\n");
head = reverse(head);
disp(head);
printf("\n\nList successfully reversed!\n");
// should free the list
return 0;
}