Doubly linked list in C: solved exercise with insert and traversal

Doubly linked list in C: solved exercise

If you searched for doubly linked list in C solved exercise, this example covers the exact interview and exam pattern: insert nodes, traverse both directions, and free memory correctly.

Problem statement

Implement a doubly linked list where each node contains:

  • value
  • next pointer
  • prev pointer

Create functions to:

  • append at the end,
  • traverse forward,
  • traverse backward,
  • free the full list.

C solution

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#include <stdio.h>
#include <stdlib.h>

typedef struct Node {
    int value;
    struct Node *next;
    struct Node *prev;
} Node;

Node *append(Node *head, int value) {
    Node *newNode = (Node *)malloc(sizeof(Node));
    if (newNode == NULL) {
        fprintf(stderr, "Memory allocation error.\n");
        return head;
    }

    newNode->value = value;
    newNode->next = NULL;
    newNode->prev = NULL;

    if (head == NULL) {
        return newNode;
    }

    Node *current = head;
    while (current->next != NULL) {
        current = current->next;
    }

    current->next = newNode;
    newNode->prev = current;
    return head;
}

Node *getTail(Node *head) {
    if (head == NULL) {
        return NULL;
    }

    while (head->next != NULL) {
        head = head->next;
    }

    return head;
}

void traverseForward(Node *head) {
    printf("Forward traversal:\n");
    while (head != NULL) {
        printf("%d ", head->value);
        head = head->next;
    }
    printf("\n");
}

void traverseBackward(Node *tail) {
    printf("Backward traversal:\n");
    while (tail != NULL) {
        printf("%d ", tail->value);
        tail = tail->prev;
    }
    printf("\n");
}

void freeList(Node *head) {
    while (head != NULL) {
        Node *tmp = head;
        head = head->next;
        free(tmp);
    }
}

int main(void) {
    Node *list = NULL;

    list = append(list, 10);
    list = append(list, 20);
    list = append(list, 30);

    traverseForward(list);
    traverseBackward(getTail(list));

    freeList(list);
    return 0;
}

Expected output

1
2
3
4
Forward traversal:
10 20 30
Backward traversal:
30 20 10

Complexity and key takeaways

  • append: O(n) due to tail search.
  • traverseForward and traverseBackward: O(n).
  • Extra space: O(1) excluding node storage.

Common mistakes

  • Forgetting to update prev when linking new nodes.
  • Losing the head reference.
  • Skipping memory cleanup.

Practical use

This pattern appears in modern event-processing tasks (logs, change streams, history navigation) where two-way traversal is useful.

Guided practice and next step

If you want a complete path with progressive difficulty:

FAQ

Is this doubly linked list exercise advanced?

It is intermediate-to-advanced. If you already know basic pointers, this is a strong next step.

Where can I find more solved C exercises?

At Programming in C in 100 Solved Exercises and in the C Exercises section. Kindle Unlimited option: View on Amazon.

How should I practice this exercise type to improve faster?

Start with small inputs, run edge cases (empty, one item, max capacity), then rewrite the solution from scratch without copying.