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
prevstarts at NULL: The first node in the original list becomes the last node in the reversed list. Itsnextpointer 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 = headmakes the node that was originally after head now point back at head.head->next = NULLsevers 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 savednxt = curr->nextfirst, the rest of the list is lost forever. - Forgetting
head->next = NULLin 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
- Reverse a String Using Pointers in C
- Stack Using Linked List in C
- Queue Using Linked List in C
- Search in a Linked List in C
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.