C Program to Reverse a Linked List

C Program to Reverse a Linked List

Reversing a linked list is a common operation that flips the order of nodes in the list. This can be useful when the last element needs to be accessed first, when implementing algorithms that require backward traversal, or when demonstrating mastery of dynamic memory and pointers in C. Understanding multiple ways to reverse a list strengthens your grasp of pointer manipulation and dynamic data structures.

Understanding the Problem

The main challenge in reversing a linked list is updating each node’s next pointer without losing access to the rest of the list. Temporary pointers, the call stack, or an auxiliary stack may be used depending on the chosen method. Edge cases, such as an empty list, a single-node list, or very long lists (for recursion), must be handled carefully to avoid segmentation faults or memory issues. Each approach—iterative, recursive, or stack-based—requires careful handling to ensure the list is correctly reversed and all nodes remain accessible.

Program 1: Add Nodes and Display

This program demonstrates how to create a linked list by adding nodes and then displaying the list. It serves as a setup for the reverse operation by showing how data is stored in sequence.

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

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

Node *head = NULL;

void insertAtEnd(int value) {

    Node *newNode = (Node*)malloc(sizeof(Node));
    newNode->data = value;
    newNode->next = NULL;

    if (!head) {
        head = newNode;
    } else {

        Node *temp = head;

        while (temp->next) {
            temp = temp->next;
        }

        temp->next = newNode;

    }

}

void display() {

    if (!head) {
        printf("Linked List is empty\n");
        return;
    }

    Node *temp = head;

    printf("Linked List: ");

    while (temp) {
        printf("%d ", temp->data);
        temp = temp->next;
    }

    printf("\n");

}

int main() {

    insertAtEnd(10);
    insertAtEnd(20);
    insertAtEnd(30);
    insertAtEnd(40);

    printf("Original List:\n");
    display();

    return 0;

}

This program shows how nodes are added at the end of the list using dynamic memory allocation. The display function prints the current sequence of nodes, providing a clear view of the list before reversing.

Program 2: Reverse the Linked List (Iterative Approach)

This program demonstrates how to reverse the linked list in place by changing the direction of the next pointers. It modifies the existing list without creating a new one.

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

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

Node *head = NULL;

void insertAtEnd(int value) {

    Node *newNode = (Node*)malloc(sizeof(Node));
    newNode->data = value;
    newNode->next = NULL;

    if (!head) {
        head = newNode;
    } else {

        Node *temp = head;

        while (temp->next) {
            temp = temp->next;
        }

        temp->next = newNode;

    }

}

void display() {

    Node *temp = head;

    if (!temp) {
        printf("Linked List is empty\n");
        return;
    }

    printf("Linked List: ");

    while (temp) {
        printf("%d ", temp->data);
        temp = temp->next;
    }

    printf("\n");

}

// Iterative method
void reverseList() {

    Node *prev = NULL, *current = head, *next = NULL;

    while (current) {
        next = current->next;   // Store next node
        current->next = prev;   // Reverse current node's pointer
        prev = current;         // Move prev forward
        current = next;         // Move current forward
    }

    head = prev; // Update head to new first node

}

int main() {

    insertAtEnd(10);
    insertAtEnd(20);
    insertAtEnd(30);
    insertAtEnd(40);

    printf("Original List:\n");
    display();

    reverseList();

    printf("Reversed List (Iterative):\n");
    display();

    return 0;

}

This iterative program reverses the linked list by updating each node’s next pointer one by one. Temporary pointers (prev, current, next) make traversal safe, preventing data loss.

Program 3: Reverse the Linked List (Recursive Approach)

This program demonstrates how to reverse the linked list using recursion. Instead of looping, it lets function calls handle the backtracking and reversal.

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

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

Node *head = NULL;

void insertAtEnd(int value) {

    Node *newNode = (Node*)malloc(sizeof(Node));
    newNode->data = value;
    newNode->next = NULL;

    if (!head) {
        head = newNode;
    } else {

        Node *temp = head;
        while (temp->next) {
            temp = temp->next;
        }

        temp->next = newNode;

    }

}

void display() {

    Node *temp = head;

    if (!temp) {
        printf("Linked List is empty\n");
        return;
    }

    printf("Linked List: ");

    while (temp) {
        printf("%d ", temp->data);
        temp = temp->next;
    }

    printf("\n");

}

// Recursive function to reverse
Node* reverseRecursive(Node *node) {

    if (!node || !node->next) {
        return node; // Last node becomes new head
    }

    Node *newHead = reverseRecursive(node->next);
    node->next->next = node; // Make next node point back to current
    node->next = NULL;       // Break current link
    return newHead;

}

void reverseListRecursive() {
    head = reverseRecursive(head);
}

int main() {

    insertAtEnd(10);
    insertAtEnd(20);
    insertAtEnd(30);
    insertAtEnd(40);

    printf("Original List:\n");
    display();

    reverseListRecursive();

    printf("Reversed List (Recursive):\n");
    display();

    return 0;

}

This recursive program works by going all the way to the last node and then flipping the pointers on the way back. It’s elegant but can be risky for very long lists because of function call stack depth.

Program 4: Reverse the Linked List (Using a Stack)

This program demonstrates how to reverse the linked list using a stack. Each node is pushed onto the stack and then popped out in reverse order, effectively rebuilding the list in reversed form.

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

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

typedef struct Stack {
    Node *node;
    struct Stack *next;
} Stack;

Node *head = NULL;
Stack *top = NULL;

// Stack operations
void push(Node *node) {

    Stack *newStackNode = (Stack*)malloc(sizeof(Stack));
    newStackNode->node = node;
    newStackNode->next = top;
    top = newStackNode;

}

Node* pop() {

    if (!top) return NULL;

    Stack *temp = top;
    Node *node = temp->node;
    top = top->next;

    free(temp);

    return node;

}

// Insert at end
void insertAtEnd(int value) {

    Node *newNode = (Node*)malloc(sizeof(Node));
    newNode->data = value;
    newNode->next = NULL;

    if (!head) {
        head = newNode;
    } else {

        Node *temp = head;

        while (temp->next) {
            temp = temp->next;
        }

        temp->next = newNode;

    }

}

// Display list
void display() {

    Node *temp = head;

    if (!temp) {
        printf("Linked List is empty\n");
        return;
    }

    printf("Linked List: ");

    while (temp) {
        printf("%d ", temp->data);
        temp = temp->next;
    }

    printf("\n");

}

// Reverse using stack
void reverseUsingStack() {

    if (!head) return;

    Node *temp = head;

    while (temp) {
        push(temp);
        temp = temp->next;
    }

    head = pop();
    temp = head;
    Node *nextNode;

    while ((nextNode = pop())) {
        temp->next = nextNode;
        temp = temp->next;
    }

    temp->next = NULL;

}

int main() {

    insertAtEnd(10);
    insertAtEnd(20);
    insertAtEnd(30);
    insertAtEnd(40);

    printf("Original List:\n");
    display();

    reverseUsingStack();

    printf("Reversed List (Stack-based):\n");
    display();

    return 0;

}

This program reverses the linked list by storing all nodes in a stack and then popping them out one by one, which naturally gives the nodes in reverse order. After popping, the list is rebuilt with reversed links, and the last node is marked with NULL to signal the new end.

FAQs

Q1: What is the time complexity of reversing a linked list?
O(n), because each node is visited exactly once.

Q2: Does reversing the list require extra memory?
No, the reversal is done in place using existing nodes, so space complexity is O(1).

Q3: Can this handle an empty list?
Yes, the function simply exits without making changes.

Q4: Can a recursive approach be used to reverse a linked list?
Yes, recursion can also reverse a linked list, but it uses extra stack space.

Conclusion

Reversing a linked list is a fundamental operation that requires careful pointer manipulation. By storing temporary references and updating the next pointers iteratively, the list can be reversed efficiently in place. Mastering this operation strengthens your understanding of dynamic data structures and pointer handling in C.

References & Additional Resources

The following books and online resources provide both theoretical foundations and practical examples to help you understand linked list operations and dynamic memory allocation in C.

  1. Kernighan, B. W., & Ritchie, D. M. (1988). The C Programming Language (2nd Edition). Prentice Hall – Classic reference on C fundamentals, including pointers and memory, critical for linked list operations.
  2. Thareja, R. (2011). Data Structures Using C. Oxford University Press – Detailed coverage of linked lists and dynamic memory allocation techniques.
  3. GeeksforGeeks: Reverse a Linked List – Step-by-step examples and explanations of reversing a linked list, with both iterative and recursive approaches.
  4. Programiz: Singly Linked List Basics – Beginner-friendly guide covering fundamental concepts and operations.
  5. Tutorialspoint: What is Dynamic Memory Allocation in C? – Explanation of malloc(), calloc(), realloc(), and free() functions for memory management in linked lists.
  6. C Standard Library Documentation – Memory Management – Official reference for memory allocation and deallocation functions in C.
Scroll to Top