What is an Adjacency List?
An adjacency list represents a graph as a collection of per-vertex neighbor lists: one entry per vertex, holding only the vertices it's actually connected to. Instead of a full V×V grid of mostly zeros, each vertex stores exactly as many entries as it has edges — nothing more.
How Does It Work?
Adding an edge (u, v) appends v to u's list. For an undirected graph, u is also appended to v's list, since the edge goes both ways; for a directed graph, only u's list gets the new entry. Checking whether an edge exists means scanning through one vertex's list looking for the target — proportional to that vertex's degree (its number of neighbors), not the whole graph.
This is the mirror image of an adjacency matrix's tradeoffs. A matrix spends O(V²) space no matter what, in exchange for O(1) edge-existence checks. A list spends space proportional to the actual number of edges — O(V + E) — but checking a specific edge now costs O(degree) instead of O(1). For the vast majority of real-world graphs, which are sparse (E is much smaller than V²), that tradeoff strongly favors the list.
Building the List
- Create an empty list (or map) for every vertex
- For every edge (u, v) with weight w: append (v, w) to u's list
- If the graph is undirected, also append (u, w) to v's list — the same edge is recorded from both directions
- To check if an edge exists between two vertices, scan the source vertex's list for the target
Complexity
- Space Complexity: O(V + E) — proportional to the actual number of vertices and edges, not V².
- Check if edge (u, v) exists: O(degree(u)) — scan u's list, which is only as long as u's actual neighbor count.
- Iterate over a vertex's neighbors: O(degree(u)) — the list already holds exactly the relevant entries.
- Add an edge: O(1) — appending to a list.
Time Complexity Analysis
Adjacency lists are the default choice for most graph algorithms — BFS, DFS, Dijkstra's algorithm, and topological sort all need to repeatedly ask "what are this vertex's neighbors?", which a list answers by directly returning exactly the relevant entries, without wasting time scanning past vertices that aren't connected at all.