Expert: advanced patterns and interviews · Graphs · topic 41 of 61 · 30 min
Graphs: vertices, edges and how to store them
Explanation
What a graph is
A graph is a set of things and the connections between them. The things are called vertices (or nodes) and the connections are called edges. A tree from Module 7 is a special graph: it is connected and has no loops. A general graph has no root, any vertex can connect to any other, and following edges can bring you back to where you started.
Graphs are everywhere once you look for them. A metro map is a graph: stations are vertices and the tracks between neighbouring stations are edges. A friends network is a graph of people. Flight routes form a graph of airports. The packages your project installs with pip or npm form a graph where "package A needs package B" is an edge.
Words you will hear
- Undirected edge: works both ways, like a two-way road or a friendship. Directed edge: has a direction, like a one-way street or "A follows B" on a social app.
- Weighted edge: carries a number, such as distance in km, travel time or ticket price. Unweighted: every edge counts the same.
- Path: a sequence of vertices where each neighbouring pair is joined by an edge. Cycle: a path that starts and ends at the same vertex.
- Connected: in an undirected graph, every vertex can reach every other. A connected component is one such separate piece; a graph can have many.
- Degree: the number of edges touching a vertex. In a directed graph, in-degree counts edges coming in and out-degree counts edges going out.
- V and E: the usual names for the number of vertices and the number of edges. A sparse graph has few edges (E close to V); a dense graph has many (E close to V²).
Three ways to store a graph
An edge list is just a list of pairs, such as [(0, 1), (1, 2)]. Interview problems usually GIVE you the graph this way, and Kruskal's algorithm (Module 10) uses it directly. But finding the neighbours of one vertex means scanning the whole list.
An adjacency matrix is a V × V grid where matrix[u][v] is 1 (or the weight) when there is an edge from u to v. Checking one edge is O(1), but it always uses V² cells, even when there are few edges. For 100,000 vertices that is 10¹⁰ cells, far too many.
An adjacency list stores, for each vertex, the list of its neighbours. It uses O(V + E) space and lists the neighbours of u in O(degree(u)) time, which is exactly what BFS and DFS need. This is the default choice in interviews.
| Structure | Space | Is u–v an edge? | Neighbours of u | Good for |
|---|---|---|---|---|
| Edge list | O(E) | O(E) | O(E) | Input format, Kruskal |
| Adjacency matrix | O(V²) | O(1) | O(V) | Small or dense graphs |
| Adjacency list | O(V + E) | O(degree(u)) | O(degree(u)) | Most problems: BFS, DFS, Dijkstra |
from collections import defaultdict
edges = [(0, 1), (0, 2), (1, 2), (2, 3)]
adj = defaultdict(list)
for u, v in edges:
adj[u].append(v)
adj[v].append(u) # undirected: store both directions
print(dict(adj))
# Output: {0: [1, 2], 1: [0, 2], 2: [0, 1, 3], 3: [2]}When the vertices are numbered 0 to n − 1, a plain list of lists is often simpler: adj = [[] for _ in range(n)]. Every vertex then has an entry, including vertices with no edges, which defaultdict would miss. For a directed graph, append only adj[u].append(v).
n = 4
matrix = [[0] * n for _ in range(n)]
for u, v in [(0, 1), (0, 2), (1, 2), (2, 3)]:
matrix[u][v] = matrix[v][u] = 1
print(matrix[2][3], matrix[0][3]) # Output: 1 0Common mistakes
- Adding only one direction for an undirected graph, so half the edges vanish. Fix: append both adj[u].append(v) and adj[v].append(u).
- Building adj = [[]] * n: all n entries are the SAME list. Fix: [[] for _ in range(n)].
- Using an adjacency matrix for a big sparse graph and running out of memory. Fix: use an adjacency list unless V is small (a few thousand at most).
- Missing isolated vertices when building from edges with defaultdict, so loops over adj skip them. Fix: loop over range(n), or create every key first.
- Mixing 1-based labels (people 1 to n) with 0-based lists. Fix: allocate n + 1 slots, or subtract 1 from every label once at the start.
- Assuming the graph is connected. Fix: ask, and when in doubt, loop over every vertex as a possible starting point.
Need help?
Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.
Try:
Watch the lesson
Graphs: vertices, edges and how to store them · 1/8
This module is about graphs: things and the connections between them. We start with the words and with how to store a graph in code.
Prefer a video by a teacher? Find free videos on “graph data structure adjacency list vs adjacency matrix explained” on YouTube ↗
In real life: A metro map as an adjacency list
A metro journey planner stores the network as a graph: each station is a vertex and each pair of neighbouring stations on a line is an undirected edge. Interchange stations, such as Rajiv Chowk in Delhi where the Blue and Yellow lines cross, have a higher degree than ordinary stations. The code below uses a tiny made-up slice of two lines (stations in between are skipped) and builds the adjacency list by joining each station to the next one on its line.
from collections import defaultdict
lines = {
"Blue": ["Dwarka", "Rajiv Chowk", "Mandi House", "Yamuna Bank"],
"Yellow": ["Kashmere Gate", "Rajiv Chowk", "Central Secretariat"],
}
adj = defaultdict(list)
for stations in lines.values():
for a, b in zip(stations, stations[1:]):
adj[a].append(b)
adj[b].append(a)
print(adj["Rajiv Chowk"])
print(len(adj["Rajiv Chowk"]), len(adj["Dwarka"]))Practice (0/3 done)
Write build_adj(n, edges) for an UNDIRECTED graph with vertices 0 to n − 1. edges is a list of pairs (u, v) with no self-loops and no repeated edges. Return a list of n lists: position u holds the neighbours of u in the order the edges appear. A vertex with no edges gets []. Example: build_adj(3, [(0, 1), (1, 2)]) returns [[1], [0, 2], [1]].
Write degrees(n, edges) for an UNDIRECTED graph with vertices 0 to n − 1 (no self-loops). Return a list where position v holds the degree of v (how many edges touch it). Example: degrees(4, [(0, 1), (0, 2), (1, 2), (2, 3)]) returns [2, 2, 3, 1].
In a town of n people labelled 1 to n, trust is a list of pairs (a, b) meaning "a trusts b". The town judge trusts nobody, and everybody else trusts the judge. Write find_judge(n, trust) that returns the judge's label, or -1 if there is no judge. Think of a directed graph: the judge has in-degree n − 1 and out-degree 0. Example: find_judge(3, [(1, 3), (2, 3)]) returns 3.
Quick quiz
Read more (free)
Related help
Before this, learn
This topic builds on these. If something here feels new, open them first.
Related topics
- Breadth-first search (BFS)Graphs · same module
- Depth-first search (DFS)Graphs · same module
- Topological sortGraphs · same module
- Minimum spanning treesTries, union-find and bit manipulation
- Core DSA patterns in C++C++ Programming (modern C++ and DSA) · Competitive programming, interviews and careers
- Union-find (disjoint set union)Tries, union-find and bit manipulation
Questions people ask about this
Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.
An undirected graph has 5 edges. What do all the degrees add up to?
Answer: 10
Every edge touches two vertices, so it adds 2 to the total: 2 × 5 = 10.
Which representation answers "is there an edge between u and v?" in O(1)?
Answer: Adjacency matrix
matrix[u][v] is read directly. The other two need a scan.
A road network has 100,000 junctions and 300,000 roads. How should you store it for BFS?
Answer: Adjacency list
A matrix would need 10¹⁰ cells; an adjacency list needs O(V + E) and gives neighbours quickly.
"Package A needs package B before it can be installed." What kind of graph is this?
Answer: Directed
The relation has a direction: A depends on B, not the other way round.
You build adj with defaultdict(list) from the edge list only. Which vertices can be missing from adj?
Answer: Vertices with no edges
A key is created only when an edge mentions the vertex, so isolated vertices never appear.
How many edges does a spanning tree of a connected graph with 10 vertices have?Related
Kahn's algorithm outputs 4 vertices of a 6-vertex graph. What does that tell you?Related
Answer: The graph has a cycle
Vertices on a cycle never reach in-degree 0, so they are left out.
From Topological sort
In word ladder, what are the vertices and the edges?Related
Answer: Words; two words that differ in exactly one letter
It is an implicit graph whose edges are generated by changing one letter.
What is the time of BFS on a graph stored as an adjacency list?Related
Answer: O(V + E)
Each vertex is queued once and each edge is checked a constant number of times.
Pass the quiz (60% or more) or mark this topic as done when you are ready.
Your progress is saved on this device only.
Next steps
- 5 more topics in “Graphs” before its exam: Breadth-first search (BFS), Depth-first search (DFS), Topological sort, Shortest paths: Dijkstra and friends, Graph problem patterns.
- Module 9 exam: Graphs · 14 questions · 25 min, without help. 6 topics of this module still to finish first.
- Then the next module, Tries, union-find and bit manipulation. 61 topics left in the course before the final exam.