How to implement a double linked list with only one pointer?
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.
Introduction
A doubly linked list normally stores two links per node: one to the previous node and one to the next. If you insist on using only one pointer-sized field per node while still supporting forward and backward traversal, the classic answer is an XOR linked list. The idea is clever, but it comes with real tradeoffs in safety, portability, and debuggability.
The Core Idea: Store prev XOR next
In a normal doubly linked list node, the links look like this conceptually:
- '
prev' - '
next'
In an XOR linked list, you store only one field, often called both, which contains:
address(prev) XOR address(next)
If you know one neighbor, you can recover the other:
next = both XOR prev
That is why traversal still works in both directions even though only one pointer-sized value is stored.
A Minimal C Representation
C is a natural language for demonstrating this because it gives direct access to addresses.
uintptr_t matters here because pointer XOR should go through an integer type designed to hold pointer values safely.
Appending Nodes
To append a node, update the old tail and the new node consistently.
The tail’s old both value effectively encoded prev XOR NULL. After appending, it must encode prev XOR newNode.
Traversing Forward
Traversal works because you always keep track of the previous node while walking.
At each step:
- '
current->bothequalsprev XOR next' - XORing that with
prevgivesnext
That is the entire mechanism.
Traversing Backward
Backward traversal is symmetrical if you keep a tail pointer.
This is why the structure behaves like a doubly linked list even though each node stores only one pointer-sized link field.
Why This Is Rare in Real Software
XOR linked lists are a classic interview or low-level data-structure exercise, but they are uncommon in production systems.
Reasons include:
- harder debugging because pointer relationships are not explicit
- poor compatibility with garbage-collected languages
- awkward interaction with sanitizers, debuggers, and memory tools
- harder insertion and deletion logic than an ordinary doubly linked list
In modern software, memory savings from one pointer per node are often not worth the maintenance cost.
Languages Where This Is a Bad Idea
Managed languages such as Java, C#, Go, and Swift are poor fits because raw address manipulation is restricted or unsafe. Even in C and C++, XOR linked lists are more of a niche technique than a recommended default.
If the real goal is lower memory usage, a different data structure may be better:
- a regular linked list with better node packing
- a dynamic array
- an indexed pool with integer offsets instead of raw pointers
Those designs are usually easier to reason about.
Common Pitfalls
A common mistake is XORing raw pointers without converting through uintptr_t. That is not the right way to express pointer arithmetic safely.
Another issue is forgetting that traversal always needs the previous node. You cannot jump to the next node from the current node alone because the stored field encodes both neighbors together.
Developers also underestimate how hard deletion becomes. Updating one node is not enough; neighboring nodes must be recomputed carefully.
Finally, this structure is difficult to inspect in a debugger because the link field is not a direct pointer to anything human-readable.
Summary
- A doubly linked list with one pointer-sized link per node is usually implemented as an XOR linked list.
- Each node stores
prev XOR nextinstead of separateprevandnextpointers. - Traversal works only because you carry the previous node along while walking the list.
- The technique is clever but significantly harder to debug and maintain than a normal doubly linked list.
- In most production code, the memory savings do not justify the complexity.
Related reading
- How to implement a Least Frequently Used LFU cache?
- How to implement a Median-heap
- How to implement a queue with three stacks?
- How to implement a repeating shuffle that's random - but not too random
- How to implement a Map with multiple keys?
- How to implement a tree data-structure in Java?
- How to implement an A algorithm?
- How to implement classic sorting algorithms in modern C?

DSA Fundamentals
Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.