Skip to content
Adjacency Lists
step 1/5

Reading — step 1 of 5

Read

~1 min readStorage

Adjacency Lists

A graph storage choice with no single right answer.

Adjacency matrix: N x N boolean array. M[i][j] = 1 iff edge from i to j.

  • Pros: O(1) edge lookup.
  • Cons: O(N²) space — useless for sparse graphs.
  • Used: small dense graphs.

Adjacency list: per node, a list of neighbors.

  • Pros: O(degree) traversal, O(N + E) space.
  • Cons: edge lookup is O(degree).
  • Used: most graph DBs.
python

Edge list (CSR for static graphs):

  • Two arrays: offsets[N+1], targets[E].
  • offsets[i] = start index in targets[] for node i.
  • Compact, cache-friendly.
  • Good for read-heavy / batch graph algorithms.

Neo4j storage:

  • Each node: pointer to first relationship.
  • Each relationship: pointers to (source, target, prev_rel, next_rel) — doubly-linked relationship list per node.
  • "Index-free adjacency": traversing a relationship = pointer dereference. O(1) per hop.

Trade-off vs SQL:

  • SQL with FK + index: edge lookup ~ B-tree height (4-5 ops).
  • Graph DB: 1 pointer (constant).
  • For deep traversals (5+ hops), graph DB is 10-100x faster.

For 100M+ edge graphs:

  • Use Compressed Sparse Row (CSR) for static analytics.
  • Batch updates separately, periodically merge into CSR.

Property storage:

  • Inline: small properties (id, name) inline in the node.
  • External: large properties (text, blobs) in separate file referenced by pointer.

Caching:

  • Nodes/edges visited by traversal often have locality.
  • Page cache + targeted in-memory caches help.

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…