Linked List Visualization — Step by Step

Linear data structure where each node points to the next. Supports insert, delete, and search with traversal.

Data StructuresbeginnerUpdated

// quick answer

Linked List is a data structures structure that runs in O(n) time on average with O(n) space. Linear data structure where each node points to the next. Supports insert, delete, and search with traversal.

How Linked List Works

A Linked List is a sequence of nodes where each node contains data and a pointer to the next node. Unlike arrays, insertion and deletion at any position is O(1) if you have a reference to the node, but accessing by index requires O(n) traversal.

Linked List Step by Step

Anatomy of a node

A linked list is a chain of nodes, each holding two things: a value and a next pointer to the following node. The list itself is just a single head pointer to the first node; the last node's next is null, marking the end. That is the whole structure. Unlike an array, the nodes are *not* contiguous in memory — each one lives wherever the allocator put it, and only the pointers hold the sequence together. This is the source of every linked-list strength (cheap local restructuring) and every weakness (no jumping to position i, poor cache behavior).

Traversal: follow the pointers

The only way to reach a node is to walk to it: start at head, follow next, repeat until you hit null. To find the value 42 in 10 → 42 → 7, you compare 10 (no), follow the pointer, compare 42 (found) — the visualizer highlights each node as the search walks past it. This is why access and search are O(n): reaching the k-th node costs k pointer hops, and there is no shortcut. Contrast an array, where a[k] is one multiply-and-add away. A linked list trades indexed access for flexible structure.

Insertion: rewiring, not shifting

Inserting at the head is two pointer writes: point the new node's next at the current head, then point head at the new node — O(1) no matter how long the list is. Inserting after any node you already hold a reference to is equally cheap: newNode.next = node.next; node.next = newNode. Compare an array, where inserting at the front shifts every element right. The catch is the word *already*: inserting at the tail or at index i first requires an O(n) walk to get there (unless you also maintain a tail pointer). The demo above builds the list by inserting each value at the tail.

Deletion needs the previous node

To delete a node you splice it out: prev.next = curr.next, and the chain simply flows around it. The subtlety is that in a singly linked list you cannot get from a node back to its predecessor, so deletion means walking with two pointers — prev trailing one step behind curr — until curr holds the target. Deleting the head is the special case with no predecessor: just advance head. The visualizer demo shows this exact dance: it searches for the middle value, then deletes it, and you can watch the neighboring pointer being rewired.

Reversing a linked list

The classic interview exercise is pure pointer choreography. Walk the list with three pointers — prev (starts null), curr (starts at head), and next — and at each node: save next = curr.next, flip the arrow with curr.next = prev, then advance prev = curr; curr = next. Trace it on 1 → 2 → 3: after step one the 1-node points at null; after step two, 2 points at 1; after step three, 3 points at 2, and prev is the new head of 3 → 2 → 1. One pass, O(n) time, O(1) extra space, every arrow reversed in place.

Linked lists vs arrays in practice

On paper linked lists win at insertion and deletion; in practice arrays usually win overall. Array elements sit side by side, so the CPU cache loads many at once, while chasing list pointers scatters across memory and stalls on every hop — a linear scan over an array is often 10–100× faster than over an equivalent list. Each node also pays pointer and allocation overhead per element. Where lists genuinely earn their keep: splicing with a node reference in hand (LRU caches), hash table collision chains, and adjacency lists — plus stacks and queues can be built on them when arrays are awkward.

Time & Space Complexity

Best CaseAverage CaseWorst CaseSpace
O(1)O(n)O(n)O(n)

Linked List Pseudocode

Linked List operations:
  insertHead(value):
    new node → head
  insertTail(value):
    traverse to end, append
  delete(value):
    find node, rewire pointers
  search(value):
    traverse until found

Press play in the visualizer above to watch each line execute with live highlighting.

Linked ListCode in JavaScript, Python & Java

JavaScript

class ListNode {
  constructor(value, next = null) {
    this.value = value;
    this.next = next;
  }
}

class LinkedList {
  head = null;

  insertHead(value) {
    this.head = new ListNode(value, this.head);
  }

  find(value) {
    let node = this.head;
    while (node !== null && node.value !== value) node = node.next;
    return node; // null if not found
  }

  delete(value) {
    if (this.head === null) return false;
    if (this.head.value === value) {
      this.head = this.head.next;
      return true;
    }
    let prev = this.head;
    while (prev.next !== null && prev.next.value !== value) prev = prev.next;
    if (prev.next === null) return false;
    prev.next = prev.next.next;
    return true;
  }
}

Python

class Node:
    def __init__(self, value, next=None):
        self.value = value
        self.next = next

class LinkedList:
    def __init__(self):
        self.head = None

    def insert_head(self, value):
        self.head = Node(value, self.head)

    def find(self, value):
        node = self.head
        while node and node.value != value:
            node = node.next
        return node  # None if not found

    def delete(self, value):
        if not self.head:
            return False
        if self.head.value == value:
            self.head = self.head.next
            return True
        prev = self.head
        while prev.next and prev.next.value != value:
            prev = prev.next
        if not prev.next:
            return False
        prev.next = prev.next.next
        return True

Java

public class LinkedList {
    private static class Node {
        int value;
        Node next;
        Node(int value, Node next) { this.value = value; this.next = next; }
    }

    private Node head;

    public void insertHead(int value) {
        head = new Node(value, head);
    }

    public boolean contains(int value) {
        for (Node n = head; n != null; n = n.next) {
            if (n.value == value) return true;
        }
        return false;
    }

    public boolean delete(int value) {
        if (head == null) return false;
        if (head.value == value) { head = head.next; return true; }
        Node prev = head;
        while (prev.next != null && prev.next.value != value) prev = prev.next;
        if (prev.next == null) return false;
        prev.next = prev.next.next;
        return true;
    }
}

When to Use Linked List

  • O(1) insert/delete when you already hold a reference to the neighboring node — the core of LRU caches (hash map pointing into a doubly linked list), free lists in allocators, and schedulers.
  • As internal plumbing for other structures: hash table collision chains, graph adjacency lists, and linked implementations of stacks and queues.
  • Frequent splicing — concatenating two lists, or removing a run of consecutive nodes — is O(1) pointer surgery, versus O(n) copying for arrays.
  • Not for indexed or random access: reaching position i costs O(n) hops. If you ever write list.get(i) in a loop, you want an array.
  • Rarely the default choice in modern code: pointer chasing is cache-hostile and each node carries allocation overhead, so dynamic arrays (JavaScript arrays, Python lists, Java ArrayList) beat linked lists in most real workloads — measure before choosing one.
  • Learn them anyway: pointer manipulation (reverse a list, detect a cycle, merge sorted lists) is a staple of interviews and the mental model behind trees and graphs.

Linked List — Frequently Asked Questions

Linked list vs array — which is faster?

Arrays, in most real situations. Array elements are contiguous, so indexed access is O(1) and scans are cache-friendly, while a linked list must hop pointer to pointer, costing O(n) to reach a position and stalling the CPU cache on every hop. Linked lists only win when you repeatedly insert or delete at a position you already hold a node reference to, avoiding the array's O(n) shifting.

What is a linked list actually used for?

Mostly as internal machinery. LRU caches pair a hash map with a doubly linked list so any entry can be moved to the front in O(1). Hash tables use short linked chains to handle collisions. Memory allocators track free blocks in linked free lists, and graph adjacency lists are often linked. Directly, application code tends to reach for dynamic arrays instead.

How do you reverse a linked list?

Walk the list once with three pointers: prev starting at null, curr at the head, and next saving where to go. At each node, store next, point curr.next back at prev, then advance both prev and curr. When curr reaches null, prev is the new head. This runs in O(n) time and O(1) extra space and is the single most common linked-list interview question.

What is the difference between singly and doubly linked lists?

A singly linked node stores one pointer, next; a doubly linked node also stores prev, pointing backward. The extra pointer lets you traverse in both directions and delete a node in O(1) given only that node, since its predecessor is reachable directly. The costs are one extra pointer of memory per node and more pointer updates to keep consistent on every insert and delete.

Why is accessing a linked list element O(n) when arrays are O(1)?

An array computes an element's memory address directly from its index, because all elements sit in one contiguous block at fixed intervals — one arithmetic step regardless of size. Linked list nodes are scattered across memory, connected only by pointers, so the address of node k is unknowable until you have followed k pointers from the head. The structure has no index; it only has a path.

Related Algorithms

References & Further Reading