POST 1 of 5 MorningDSAConcept
Adjacency list — the only graph rep you need most days
Three ways to represent a graph in code. Each makes different operations cheap.
One — adjacency list. A dict (or list of lists) mapping each node to its neighbours. graph[node] returns the list of neighbours. Memory O(V + E). Iteration over neighbours is fast. Edge existence check is O(degree). Default for sparse graphs (most real graphs).
Two — adjacency matrix. An n×n boolean (or weight) array. matrix[u][v] is true if there's an edge from u to v. Memory O(V²). Edge existence is O(1). Iteration over neighbours is O(V) — you scan the row. Useful when graphs are dense (close to n² edges) or you query edge existence frequently.
Three — edge list. A list of (u, v) pairs. Memory O(E). Iteration over all edges is fast. Iteration over neighbours of a single node is O(E) — slow. Useful for algorithms that process all edges (Kruskal's MST), almost never for traversal.
For the 99% of practical graph work — adjacency list, with defaultdict(list).
from collections import defaultdict
graph = defaultdict(list)
for u, v in edges:
graph[u].append(v)
graph[v].append(u) # undirected
Now graph[node] is the neighbour list. Iteration is fast. Memory matches the actual edge count.
Real-world graphs are almost always sparse. Social networks have average degree maybe 200, on networks of millions of users — way fewer than V² edges. Adjacency list is right.
The rare cases for matrix — small dense graphs (V < 1000), all-pairs shortest paths algorithms (Floyd-Warshall), or when edge-existence queries dominate. Otherwise adjacency list.
Learn one rep well. Most algorithms (BFS, DFS, Dijkstra, topological sort) work directly on adjacency lists.#DSA#Algorithms#Python#100DaysOfCode#CodingInterview#Graphs