Search code examples
creversesingly-linked-listcircular-listfunction-definition

Why isn't my reverse(); function working?


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");
}

Solution

  • 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;
    }