Doubly Linked List

Basic Algorithms
≈ 2 min read

References in both directions

In a doubly linked list, a node stores two links: next goes forward, while prev goes backward. Therefore, given a reference to a particular node, we can immediately reach both of its neighbors.

class Node {
    int value;
    Node prev;
    Node next;

    Node(int value) {
        this.value = value;
    }
}

The convenience costs one additional reference per node and more careful structural updates: when inserting or removing, we usually have to keep both directions consistent.

Removing a known node

If we already have a reference to the node being removed, its neighbors can be connected directly. For an internal node, the operation does not require searching for the previous element.

if (node.prev != null) {
    node.prev.next = node.next;
}

if (node.next != null) {
    node.next.prev = node.prev;
}

The number of assignments is constant, so removing a known node itself takes O(1). The list boundaries still require attention, however: removing the head or tail also requires updating the external head or tail reference.

When a doubly linked structure helps

A doubly linked structure is useful when an algorithm needs to move in both directions, remove already located nodes quickly, or maintain access to both ends of a list. If backward movement is unnecessary, the extra prev reference may be unnecessary overhead.

The main invariant is that neighboring references must agree. If a.next == b, then for neighboring nodes we also expect b.prev == a. A mistake in only one direction can easily leave the structure inconsistent.