Reverse a Linked List in C – Iterative and Recursive Approaches

To reverse a linked list in C, walk through the list with three pointers — prev, curr, and nxt — flipping each node’s next pointer to point backwards as you go. When curr reaches NULL you have finished, and prev is the new head. This iterative approach runs in O(n) time and O(1) space and is the expected answer in technical interviews. This page shows both the iterative and recursive approaches in C, with a complete pointer trace and a working program you can compile.

How the Iterative Reversal Works

The key challenge is that once you flip curr->next to point backwards, you lose access to the rest of the list. The fix is to save the next node before flipping.

Before the loop
List 10 → 20 → 30 → 40 → 50 → NULL
prev NULL
curr → 10
Step nxt (saved) Flip curr→next to prev advances to curr advances to
1 → 20 NULL → 10 → 20
2 → 30 → 10 → 20 → 30
3 → 40 → 20 → 30 → 40
4 → 50 → 30 → 40 → 50
5 NULL → 40 → 50 NULL
Done new head = 50

Result: 50 → 40 → 30 → 20 → 10 → NULL

C Program: Reverse Linked List (Iterative and Recursive)

/* Reverse a linked list — iterative and recursive approaches
 * Compile: gcc -ansi -Wall -Wextra revlist.c -o revlist */
#include <stdio.h>
#include <stdlib.h>

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

struct node *new_node(int data)
{
    struct node *n = (struct node *)malloc(sizeof(struct node));
    if (!n) { printf("Out of memory.\n"); exit(1); }
    n->data = data;
    n->next = NULL;
    return n;
}

struct node *append(struct node *head, int data)
{
    struct node *cur, *n = new_node(data);
    if (!head) return n;
    for (cur = head; cur->next; cur = cur->next) ;
    cur->next = n;
    return head;
}

void print_list(struct node *head)
{
    for (; head; head = head->next) {
        printf("%d", head->data);
        if (head->next) printf(" -> ");
    }
    printf(" -> NULL\n");
}

void free_list(struct node *head)
{
    struct node *tmp;
    while (head) { tmp = head->next; free(head); head = tmp; }
}

/* --- Iterative reversal: three-pointer technique --- */
struct node *reverse_iter(struct node *head)
{
    struct node *prev = NULL;
    struct node *curr = head;
    struct node *nxt;
    while (curr) {
        nxt        = curr->next;  /* 1. save the next node */
        curr->next = prev;        /* 2. flip the link */
        prev       = curr;        /* 3. advance prev */
        curr       = nxt;         /* 4. advance curr */
    }
    return prev;                  /* prev is now the new head */
}

/* --- Recursive reversal: fix links from the tail backwards --- */
struct node *reverse_rec(struct node *head)
{
    struct node *new_head;
    if (!head || !head->next) return head;   /* 0 or 1 node */
    new_head          = reverse_rec(head->next); /* reverse the tail */
    head->next->next  = head;    /* tail's last node points back */
    head->next        = NULL;    /* cut head from the forward list */
    return new_head;
}

int main(void)
{
    struct node *list = NULL;
    int n, i, val;

    printf("Enter number of nodes: ");
    if (scanf("%d", &n) != 1 || n <= 0) {
        printf("Invalid.\n"); return 1;
    }
    for (i = 0; i < n; i++) {
        printf("Node %d value: ", i + 1);
        if (scanf("%d", &val) != 1) { printf("Invalid.\n"); return 1; }
        list = append(list, val);
    }

    printf("\nOriginal:              ");
    print_list(list);

    list = reverse_iter(list);
    printf("After iterative reverse: ");
    print_list(list);

    /* Restore, then show recursive reversal */
    list = reverse_iter(list);
    list = reverse_rec(list);
    printf("After recursive reverse: ");
    print_list(list);

    free_list(list);
    return 0;
}

Sample Output

Enter number of nodes: 5
Node 1 value: 10
Node 2 value: 20
Node 3 value: 30
Node 4 value: 40
Node 5 value: 50

Original:              10 -> 20 -> 30 -> 40 -> 50 -> NULL
After iterative reverse: 50 -> 40 -> 30 -> 20 -> 10 -> NULL
After recursive reverse: 50 -> 40 -> 30 -> 20 -> 10 -> NULL

Code Explanation

  • Three-pointer pattern (prev, curr, nxt): All the work happens in four assignment lines inside the while loop. Step 1 saves the forward reference before we destroy it. Step 2 is the actual reversal — flipping the link. Steps 3 and 4 slide both pointers one node forward so the loop continues from the correct position.
  • Why prev starts at NULL: The first node in the original list becomes the last node in the reversed list. Its next pointer must be NULL (end of list). Initializing prev=NULL makes this happen automatically at step 2 of the first iteration.
  • Recursive approach — the two key lines: head->next->next = head makes the node that was originally after head now point back at head. head->next = NULL severs head’s original forward link so it doesn’t create a cycle. Combined, these two lines attach head to the end of the already-reversed tail.
  • The cast in malloc: (struct node *)malloc(...) — in C89, void* is not implicitly converted to other pointer types (unlike C++), so the cast is required.
  • Memory management: free_list() walks the list and frees each node. Skipping this in real programs causes a memory leak equal to the total size of the list.

Iterative vs Recursive: Key Differences

Property Iterative Recursive
Time complexity O(n) O(n)
Space complexity O(1) — three pointers only O(n) — one stack frame per node
Stack overflow risk None Yes for very long lists
Readability Clear once the pointer pattern is understood Elegant but harder to trace
Preferred in interviews Yes — O(1) space is better Shows recursion knowledge

Common Mistakes

  • Not saving nxt before flipping: Once you execute curr->next = prev, the original forward link is gone. If you have not saved nxt = curr->next first, the rest of the list is lost forever.
  • Forgetting head->next = NULL in the recursive version: Without this line, the original head still points forward to its old neighbour, creating a cycle in the reversed list.
  • Returning curr instead of prev: At the end of the iterative loop, curr is NULL (went past the last node). The new head is prev. Returning curr gives you a null pointer.

Frequently Asked Questions

How do you reverse a doubly linked list in C?

For a doubly linked list, swap the next and prev pointers of every node, then return the node that was previously the tail. Walk the list, and at each node: tmp = cur->prev; cur->prev = cur->next; cur->next = tmp; last = cur; cur = cur->prev; (using the newly-swapped prev, which was originally next). When the loop ends, last is the new head.

How do you reverse a linked list in groups of k?

Process the list in chunks of k nodes. For each chunk, apply the iterative three-pointer reversal, then connect the reversed chunk’s tail to the next chunk’s reversed head. Recurse or iterate over the remaining nodes. This requires tracking the tail of each reversed chunk so you can link it forward.

Related Programs

Recommended books:
The C Programming Language — K&R (India) |
(US)
 | 
C Programming: A Modern Approach — K.N. King (India) |
(US)

Test your C knowledge: C Aptitude Questions — or try our C Programming Quiz App on Android.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>