Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Chapter 32: Synthesis and Future Directions

32.1 The Data Structure Spectrum

From fundamental to application-specific:

Abstraction Level
├── Fundamental: Array, List, Tree, Hash, Graph
│
├── Composite: Skip lists, Tries, Heaps, Bloom filters
│
├── Specialized: Segment trees, B-trees, LSM trees
│
├── Distributed: DHT, CRDT, Raft state machines
│
└── Application: Routing tables, Inverted indexes,
                Time series stores, Graph DBs

The layers are not just an organising convenience. each one is built by composing the layer beneath it, and tracing a structure down through the stack usually explains why it behaves the way it does.

A routing table is a trie is a tree is pointers into memory. An LSM tree is sorted runs plus a memtable plus Bloom filters, which are a bit array plus hash functions. A DHT is a hash function plus a ring plus a routing table plus failure detection. Nothing at the top of this diagram is novel at the bottom of it.

Read the other direction, the same diagram is a map of what changes as you ascend:

LevelThe binding constraintWhat you optimise
FundamentalCPU cycles, cache linesOperation count, locality
CompositeMemory footprintBits per element, pointer overhead
SpecializedDisk and page transfersI/O count, write amplification
DistributedNetwork round trips, partitionsCoordination avoided
ApplicationHuman requirementsThe right approximation

Complexity analysis is most useful at the top two rows and least useful at the bottom two. Nobody chooses between two distributed designs by comparing O(log n) to O(1); they compare round trips, failure modes, and what happens during a partition. The asymptotics have not become wrong, they have become the least interesting term.

32.2 Emerging Paradigms

Learned Data Structures

Machine learning models replacing traditional structures:

  • Learned indexes: Replace B-trees with neural networks predicting data positions
  • Learned cardinalities: Better statistics for query optimization
  • Learned compression: Adaptive compression based on data distribution

Neural B-tree:

Input: key
Output: predicted position + confidence interval

Training: Supervised learning on key distributions
Prediction: Binary search within confidence bounds

The reframing is genuine: an index is a function from key to position, and a model can approximate a function. A B-tree assumes nothing whatsoever about the key distribution, which makes it robust and also means it throws away information. Real key distributions (timestamps, auto-increment IDs, sorted identifiers)are highly regular, and a model that captures that regularity beats a structure that ignores it.

The honest status, five years on from the original paper: learned indexes remain mostly research, and the parts that shipped are elsewhere. Updates are the hard problem. The original design was read-only, and while ALEX and the PGM-index support updates, distribution shift can force retraining. Worst-case bounds disappear, which matters for anything adversarial. And “neural network” oversells it: the models that work are staged linear regressions, because inference has to cost nanoseconds.

What has landed from this line of work is less glamorous and more useful: learned cardinality estimation in query optimisers, learned cache-eviction policies, and learned Bloom filters. Chapter 19 covers the details.

Quantum Data Structures

Quantum computing offers new primitives:

  • Quantum search: O(√n) search (Grover’s algorithm)
  • Quantum random access memory (QRAM): Sub-linear access with superposition
  • Quantum fingerprints: Exponential space reduction for equivalence testing

Worth stating the caveats plainly, because this area attracts more enthusiasm than it currently earns.

Grover’s algorithm gives a quadratic speedup for unstructured search: O(√n) instead of O(n). That is real but modest, and it applies to unstructured search. A sorted array with binary search is already O(log n), which beats O(√n) comfortably. Grover helps where no structure exists to exploit, which is precisely the case where you would normally add an index.

QRAM is the deeper problem. Most quantum algorithms with impressive speedups assume a memory that can be queried in superposition, and no scalable QRAM has been built. The theoretical speedups are frequently accounted without the cost of loading classical data into quantum state, which can erase the advantage entirely.

The realistic near-term position: quantum computing will likely matter first for simulation, optimisation, and cryptography, not for data structures. The exception is cryptographic hashing: Grover halves the effective bit strength of a hash function, which is why post-quantum guidance recommends 256-bit hashes where 128 was sufficient. That is a live concern for Merkle trees and content-addressed storage.

32.3 The Road Ahead

Software-hardware co-design: As memory hierarchies deepen (NVM, CXL), data structures must adapt. Cache-oblivious structures gain importance.

Specialized accelerators: FPGAs and ASICs for network processing, search, and analytics push structure design toward hardware.

Declarative data structures: The boundary between algorithms and data structures blurs as query optimizers automatically choose structures based on workload patterns.

Two shifts already underway deserve to be added, because they are changing decisions today rather than eventually.

Vector search became infrastructure in about three years. Embedding models turned similarity search from a niche problem into a default component of application architecture, and the structures that serve it (HNSW graphs, IVF, product quantization)went from papers to production defaults faster than almost anything in this book’s history. Note what drove it: not a better algorithm, but a change in what data looked like. Structures follow workloads.

NVMe is quietly reopening settled questions. A great deal of received wisdom: B-trees over hash indexes on disk, LSM trees over in-place updates, “random I/O is catastrophic”. Was calibrated against spinning disks where a seek cost 10ms. On NVMe a random read costs about 10μs, a thousandfold improvement, and the gap between sequential and random access narrows from 10,000× to something closer to 10×. Several tradeoffs that were obvious in 2005 are now genuinely arguable. When the hardware assumptions under a piece of conventional wisdom change by three orders of magnitude, the wisdom deserves rechecking.

The general lesson across both: the structures that win are the ones that answer a question created by a hardware or workload shift. LSM trees won when write amplification on flash started to matter. HNSW won when embeddings created a new query type. Neither was primarily an algorithmic advance.

32.4 Principles for the Practitioner

  1. Measure before optimizing: Profile against real workloads
  2. Understand trade-offs: Every structure excels in some dimensions
  3. Prefer simplicity: Complex structures have hidden costs
  4. Plan for scale: Design for 10x growth
  5. Embrace approximation: Probabilistic structures often suffice
  6. Consider distribution: At scale, single-machine solutions fail
  7. Document assumptions: Workload characteristics drive structure choice

Four of those are worth sharpening, because as stated they are easy to agree with and hard to act on.

Measure the right thing. “Profile” usually means a wall-clock profiler, which tells you where time goes but not why. If a function is slow and its arithmetic is trivial, the answer is memory, and you need hardware counters to see it. An instructions-per-cycle figure below 1.0 with high cache misses means the layout is wrong and no algorithmic tuning will help: see Chapter 22.

Prefer simplicity, and mean it. The most common real-world mistake is not picking an O(n log n) structure where O(n) existed. It is picking a sophisticated structure whose constant factors, memory overhead, and bug surface exceed the benefit. Fibonacci heaps are the standing example: optimal on paper, beaten by binary heaps in practice, and vastly harder to get right. A linear scan over a contiguous array beats almost everything below a few hundred elements.

“Design for 10× growth” is a claim about which dimension grows. Ten times the data is a different problem from ten times the write rate, which is different again from ten times the concurrent readers. B-trees handle the first, LSM trees the second, immutable structures the third. Designing for unspecified “scale” produces systems that are complex in the wrong direction.

Embrace approximation, after checking the error direction. A Bloom filter’s false positives are safe as a cache filter and unsafe as an access-control check. The question is never just “is approximate good enough” but “what does a mistake cost, and which way does this structure make them” (Chapter 14).

Three more that this book has argued throughout:

  1. Identify the repeated question. Every algorithm asks one thing over and over. “which is nearest”, “have I seen this”, “would this create a cycle”. Name it, and the structure is usually obvious. Get it wrong and no optimisation will save you (Chapter 21).

  2. Abstract the interface, document the cost. A List backed by an array and one backed by a linked list have identical signatures and completely different performance. Hiding the layout is good design; hiding the cost is how O(n²) loops get written by accident.

  3. Write the invariant checker. For every structure there is a predicate that must hold after every operation. Written as code and asserted in debug builds, it converts a silent wrong answer a thousand operations later into a failure on the operation that caused it.

32.5 A Closing Thought

The through-line of these thirty-one chapters is that there are far fewer ideas here than there are structures. Almost everything in this book is one of a handful of moves, applied at a different scale:

  • Divide the space so most of it can be discarded: binary search, trees, tries, KD-trees, sharding.
  • Trade exactness for space: Bloom filters, HyperLogLog, sketches, learned indexes.
  • Trade space for time, or the reverse: indexes, caches, memoization, compression.
  • Batch the expensive thing: LSM trees, B-tree fanout, external sorting, request coalescing.
  • Share what didn’t change: persistent structures, copy-on-write, Git, snapshots, Merkle trees.
  • Randomize to defeat the adversary: skip lists, treaps, universal hashing, randomized pivots.
  • Never mutate; append and reference: logs, event sourcing, immutable collections, Kafka, Delta Lake.

Each of those appears at every level of the spectrum in §32.1, from cache lines to continents. A B-tree fans out to reduce disk transfers; a CDN hierarchy fans out to reduce origin requests; both are the same move against a different cost. Recognising which move a system is making is usually faster than learning the system.

New structures will keep arriving, and most will not last. The survivors are the ones answering a question that new hardware or a new workload just created. But they will be built from these same moves, because the moves are responses to constraints that have not changed: memory is a hierarchy, coordination is expensive, and you cannot have everything at once.

That last constraint is the one this book opened with, in Chapter 1: there is no free lunch. Every structure is fast at something because it agreed to be slow at something else. Knowing what a structure gave up is knowing when to use it.


Where this connects