Skip to content

Expert: advanced patterns and interviews · Graphs · topic 41 of 61 · 30 min

Graphs: vertices, edges and how to store them

Explanation

A graph is a set of things (vertices) and the connections between them (edges). Edges can have a direction and a weight, and a graph can have cycles and several separate pieces. You store a graph as an edge list, an adjacency matrix or, most often in interviews, an adjacency list, which takes O(V + E) space.

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²).
Tip: In any undirected graph, the degrees add up to exactly 2 × E, because every edge touches two vertices. This is called the handshake lemma, and it is a quick way to check your code.

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.

StructureSpaceIs u–v an edge?Neighbours of uGood for
Edge listO(E)O(E)O(E)Input format, Kruskal
Adjacency matrixO(V²)O(1)O(V)Small or dense graphs
Adjacency listO(V + E)O(degree(u))O(degree(u))Most problems: BFS, DFS, Dijkstra
python
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]}
defaultdict(list) creates an empty list the first time a vertex is used, so there is no KeyError.

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).

python
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 0
The same graph as an adjacency matrix: O(1) edge checks, O(V²) memory.

Common 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

Graphs

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.

python
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"]))
Shows the four neighbours of Rajiv Chowk, then 4 1: the interchange has degree 4, the end station degree 1.

Practice (0/3 done)

Task 1 · Code · Python

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]].

Task 2 · Code · Python

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].

Task 3 · Code · Python

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

Question 1

1.An undirected graph has 5 edges. What do all the degrees add up to?

Question 2

2.Which representation answers "is there an edge between u and v?" in O(1)?

Question 3

3.A road network has 100,000 junctions and 300,000 roads. How should you store it for BFS?

Question 4

4."Package A needs package B before it can be installed." What kind of graph is this?

Question 5

5.You build adj with defaultdict(list) from the edge list only. Which vertices can be missing from adj?

Read more (free)

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

Answer: 9

A tree on V vertices always has V − 1 edges.

From Minimum spanning trees

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.

From Graph problem patterns

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.

From Breadth-first search (BFS)

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

  1. 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.
  2. Module 9 exam: Graphs · 14 questions · 25 min, without help. 6 topics of this module still to finish first.
  3. Then the next module, Tries, union-find and bit manipulation. 61 topics left in the course before the final exam.

← Previous: More greedy classics