Linked Lists: Introduction to Nodes and Pointers
A linked list is a linear data structure where each element, called a node, holds a value plus a pointer (a reference) to the next node. Instead of sitting side by side in memory like an array, the nodes can live anywhere — they are chained together by these links. This page explains what a node is, how the chain works, and when a linked list beats an array.

What a node is
Each node bundles two things: the data it stores and a link to the next node. The list itself is just a pointer to the first node, called the head. The last node points to nothing (null / nullptr / None), marking the end.
struct Node {
int data;
Node* next;
Node(int v) : data(v), next(nullptr) {}
};
class Node {
int data;
Node next;
Node(int v) { data = v; next = null; }
}
class Node {
constructor(value) {
this.data = value;
this.next = null;
}
}
class Node:
def __init__(self, value):
self.data = value
self.next = None
How the chain works
Picture a treasure hunt: the head is your first clue, and every clue tells you where the next one is. To reach the third node you must start at the head and follow next twice — there is no way to jump straight to position i. That is the defining trade-off of linked lists.
// Build 10 -> 20 -> 30
Node* head = new Node(10);
head->next = new Node(20);
head->next->next = new Node(30);
// Walk the chain
for (Node* cur = head; cur != nullptr; cur = cur->next)
std::cout << cur->data << " ";
// Build 10 -> 20 -> 30
Node head = new Node(10);
head.next = new Node(20);
head.next.next = new Node(30);
// Walk the chain
for (Node cur = head; cur != null; cur = cur.next)
System.out.print(cur.data + " ");
// Build 10 -> 20 -> 30
const head = new Node(10);
head.next = new Node(20);
head.next.next = new Node(30);
// Walk the chain
for (let cur = head; cur !== null; cur = cur.next)
console.log(cur.data);
# Build 10 -> 20 -> 30
head = Node(10)
head.next = Node(20)
head.next.next = Node(30)
# Walk the chain
cur = head
while cur is not None:
print(cur.data)
cur = cur.next
Linked list vs array
Both store a sequence, but they make opposite trade-offs:
| Operation | Array | Linked list |
|---|---|---|
| Access by index | O(1) | O(n) — must walk |
| Insert/delete at front | O(n) — shift all | O(1) |
| Insert/delete at end | O(1) amortized | O(1) with a tail pointer |
| Insert/delete in middle | O(n) | O(1) once you hold the node |
| Memory layout | contiguous | scattered + extra pointer per node |
| Cache friendliness | excellent | poor |
The headline: arrays win at random access, linked lists win at inserting and deleting at the ends without shifting anything. Linked lists also grow one node at a time, so there is no costly resize or wasted capacity.
For beginners: A “pointer” or “reference” is just the address of another node — a way to say “the next item lives over there.” Following a pointer is called traversing or walking the list.
Going deeper: Linked lists trade memory locality for flexibility. Because nodes are scattered, the CPU cache cannot prefetch them efficiently, so in practice an array often outruns a linked list even for tasks the Big-O table says they tie on. Measure before assuming.
The flavors of linked list
- Singly linked list — each node points only forward.
- Doubly linked list — each node points forward and backward.
- Circular linked list — the last node links back to the head.
When to use a linked list
Reach for a linked list when you frequently insert or remove at the front (a stack or queue built on nodes), when you don’t need index access, or when you want a structure that grows without reallocation. If you need fast lookup by position or by key, prefer an array or a hash table.
Next, build one from scratch with the singly linked list page, or jump to the core operations.