Code Snippets
/

Doubly Linked List Template

Doubly Linked List Template

A doubly linked list adds a `prev` pointer to every node, which unlocks O(1) removal of a known node and O(1) traversal in both directions. This is the structural backbone of LRU caches, browser back / forward stacks, and skip-list-adjacent designs. This snippet covers the Node + List skeleton with sentinel head and tail, the unlink-known-node operation that makes LRU possible, and a forward / backward iteration helper.

JavaScript
Medium
3 snippets
data-structures
linked-list
code-template
algorithms

257 views

7

class DLNode {
    constructor(value) {
        this.value = value;
        this.prev = null;
        this.next = null;
    }
}

class DoublyLinkedList {
    constructor() {
        this.head = new DLNode(null);
        this.tail = new DLNode(null);
        this.head.next = this.tail;
        this.tail.prev = this.head;
        this.size = 0;
    }
    pushBack(value) {
        const node = new DLNode(value);
        node.prev = this.tail.prev;
        node.next = this.tail;
        this.tail.prev.next = node;
        this.tail.prev = node;
        this.size++;
        return node;
    }
    toArray() {
        const out = [];
        for (let n = this.head.next; n !== this.tail; n = n.next) out.push(n.value);
        return out;
    }
}

const d = new DoublyLinkedList();
d.pushBack(1); d.pushBack(2); d.pushBack(3);
console.log(d.toArray()); // [1, 2, 3]

Sentinel head and tail nodes (with value: null) eliminate every 'is this the first or last node?' branch from the rest of the API. Insert and remove both become four pointer assignments with no special cases. The trade-off is two extra nodes in memory, which is negligible for any list big enough to care about doubly-linked semantics. Returning the inserted node from pushBack lets callers cache a handle for O(1) removal later, which is the operation LRU caches depend on.