Skip to content
  • Doubly & Circular Linked Lists · C

Doubly & Circular Linked Lists

LearnViaNotes @learnvianotes· 2 min read

A doubly linked list stores prev and next pointers, so a node can be removed in O(1) given only a pointer to it and the list can be walked both ways.

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

typedef struct DNode {
    int data;
    struct DNode *prev, *next;
} DNode;

/* circular list with a sentinel: no NULL checks at the ends */
typedef struct { DNode head; size_t size; } List;

void list_init(List *l) { l->head.prev = l->head.next = &l->head; l->size = 0; }

void insert_after(List *l, DNode *pos, int v) {
    DNode *n = malloc(sizeof *n);
    if (!n) exit(1);
    n->data = v;
    n->prev = pos;
    n->next = pos->next;
    pos->next->prev = n;
    pos->next = n;
    l->size++;
}

void push_front(List *l, int v) { insert_after(l, &l->head, v); }
void push_back(List *l, int v)  { insert_after(l, l->head.prev, v); }

void unlink_node(List *l, DNode *n) {        /* O(1): no search for the predecessor */
    n->prev->next = n->next;
    n->next->prev = n->prev;
    free(n);
    l->size--;
}

void print(const List *l) {
    for (const DNode *n = l->head.next; n != &l->head; n = n->next) printf("%d ", n->data);
    printf("| backwards: ");
    for (const DNode *n = l->head.prev; n != &l->head; n = n->prev) printf("%d ", n->data);
    printf("(size %zu)\n", l->size);
}

int main(void) {
    List l;
    list_init(&l);
    push_back(&l, 2); push_back(&l, 3); push_front(&l, 1); push_back(&l, 4);
    print(&l);
    unlink_node(&l, l.head.next->next);       /* remove the 2 */
    print(&l);
    while (l.size) unlink_node(&l, l.head.next);
    print(&l);
    return 0;
}
Output
1 2 3 4 | backwards: 4 3 2 1 (size 4)
1 3 4 | backwards: 4 3 1 (size 3)
| backwards: (size 0)
VariantProsCons
Singly linkedSmallest nodes, simplestCan’t go back; deleting needs the predecessor
Doubly linkedO(1) delete of any node, both directionsTwo pointers per node
CircularRound-robin traversal; no NULL endMust stop by comparing with the start

Why is deletion O(1) in a doubly linked list but O(n) in a singly linked one?

Free for students and teachers

Write notes like this one

Cards for every idea, quizzes and flashcards, read aloud — on the web and your phone.

Something wrong with this note? Open it to report