Section 4 · 8 min read

Graphs as a data structure

Graph vocabulary and counting facts, and how adjacency matrices, adjacency lists, edge lists and incidence matrices store a graph, with the space and time cost of each.

On this page
  1. Vocabulary
  2. Counting facts
  3. Representations
  4. Matrix powers count walks
  5. Storing a graph compactly
  6. Worked examples
  7. Common traps
  8. Quick revision

Vocabulary

A graph G=(V,E)G = (V, E) has a set of vertices VV and a set of edges EE. Write n=∣V∣n = |V| and m=∣E∣m = |E|.

  • Undirected: an edge {u,v}\{u, v\} has no direction. Directed: an edge (u,v)(u, v) goes from uu to vv.
  • Simple graph: no self-loops and no parallel edges. GATE assumes simple graphs unless it says otherwise.
  • Weighted: each edge carries a number.
  • Degree deg⁡(v)\deg(v): number of edges at vv. In a directed graph, in-degree and out-degree are counted separately.
  • Walk: a sequence of vertices joined by edges, repeats allowed. Path: no repeated vertices. Cycle: a closed path.
  • Connected (undirected): a path exists between every pair. Strongly connected (directed): a directed path exists both ways between every pair.
  • Component: a maximal connected subgraph.
  • Tree: connected and acyclic; equivalently connected with n−1n - 1 edges; equivalently acyclic with n−1n - 1 edges.
  • Bipartite: vertices split into two sides with every edge crossing between them. A graph is bipartite exactly when it has no odd cycle.

Counting facts

  • Handshake lemma: ∑vdeg⁡(v)=2m\sum_v \deg(v) = 2m in an undirected graph. So the number of odd-degree vertices is even.
  • In a directed graph, ∑vin(v)=∑vout(v)=m\sum_v \text{in}(v) = \sum_v \text{out}(v) = m.
  • A simple undirected graph has at most (n2)=n(n−1)2\binom{n}{2} = \frac{n(n-1)}{2} edges; a simple directed graph at most n(n−1)n(n-1).
  • The number of distinct simple undirected graphs on nn labelled vertices is 2(n2)2^{\binom{n}{2}}.
  • A forest with nn vertices and kk components has n−kn - k edges.
  • A graph with nn vertices and kk components has at least n−kn - k edges, and at most (n−k+12)\binom{n - k + 1}{2} edges (one big complete component plus k−1k - 1 isolated vertices).
  • The largest disconnected simple graph on nn vertices has (n−12)\binom{n-1}{2} edges. Any simple graph with more edges is connected.
  • A complete bipartite graph Ka,bK_{a,b} has abab edges.

Representations

Adjacency matrix

An n×nn \times n matrix AA with A[i][j]=1A[i][j] = 1 if there is an edge from ii to jj (or the weight, for weighted graphs).

#define N 5
int A[N][N];                       /* A[i][j] = 1 if edge i -> j */

void addEdge(int u, int v) {       /* undirected */
    A[u][v] = 1;
    A[v][u] = 1;
}
  • Space Θ(n2)\Theta(n^2) regardless of mm.
  • Edge test O(1)O(1).
  • Listing the neighbours of vv: Θ(n)\Theta(n), a full row.
  • For an undirected graph the matrix is symmetric, and the diagonal is zero for a simple graph.
  • Row sum of row ii is the out-degree of ii; column sum of column jj is the in-degree of jj.

Adjacency list

An array of nn lists; the list of uu holds every vv with an edge (u,v)(u, v).

struct edge { int to; struct edge *next; };
struct edge *adj[N];               /* adj[u] is the head of u's list */

void addArc(int u, int v) {        /* directed u -> v, inserted at the front */
    struct edge *e = malloc(sizeof *e);
    e->to = v;
    e->next = adj[u];
    adj[u] = e;
}
  • Space Θ(n+m)\Theta(n + m). An undirected edge appears in two lists, so there are 2m2m list nodes; a directed graph has mm.
  • Edge test (u,v)(u, v): O(deg⁡(u))O(\deg(u)).
  • Listing the neighbours of vv: Θ(deg⁡(v))\Theta(\deg(v)).
  • Out-degree of uu is the length of its list. In-degree needs a pass over all lists: Θ(n+m)\Theta(n + m) for all vertices at once.

Edge list and incidence matrix

  • Edge list: an array of mm pairs (or triples with weights). Space Θ(m)\Theta(m). Natural input for Kruskal's algorithm, which sorts edges.
  • Incidence matrix: n×mn \times m, with entry (v,e)=1(v, e) = 1 when vertex vv is an end of edge ee. In an undirected graph every column has exactly two 1s; for a directed graph one end is marked +1+1 and the other −1-1. Space Θ(nm)\Theta(nm).

Choosing a representation

Task Adjacency matrix Adjacency list
Space Θ(n2)\Theta(n^2) Θ(n+m)\Theta(n + m)
Is (u,v)(u, v) an edge? O(1)O(1) O(deg⁡(u))O(\deg(u))
Visit all neighbours of uu Θ(n)\Theta(n) Θ(deg⁡(u))\Theta(\deg(u))
BFS or DFS of the whole graph Θ(n2)\Theta(n^2) Θ(n+m)\Theta(n + m)
Add an edge O(1)O(1) O(1)O(1) at the list head
Remove an edge O(1)O(1) O(deg⁡(u))O(\deg(u))
Transpose (reverse all edges) Θ(n2)\Theta(n^2) Θ(n+m)\Theta(n + m)

Since m≤n2m \le n^2, lists are never worse than the matrix for traversals. Use a matrix for dense graphs (mm close to n2n^2), for frequent edge tests, or for algorithms that work on the matrix directly, such as Floyd-Warshall. Use lists for sparse graphs, which most real graphs are.

Matrix powers count walks

For an adjacency matrix AA (entries 0 or 1),

(Ak)ij=number of walks of length k from i to j(A^k)_{ij} = \text{number of walks of length } k \text{ from } i \text{ to } j

because (A2)ij=∑tAitAtj(A^2)_{ij} = \sum_t A_{it} A_{tj} counts the middle vertices tt with edges ii to tt and tt to jj, and the argument extends by induction.

Useful specialisations for a simple undirected graph:

  • (A2)ii=deg⁡(i)(A^2)_{ii} = \deg(i), since a closed walk of length 2 goes to a neighbour and back.
  • trace(A2)=2m\text{trace}(A^2) = 2m.
  • trace(A3)=6×\text{trace}(A^3) = 6 \times (number of triangles), since each triangle gives 3 starting vertices times 2 directions.

Storing a graph compactly

When the graph is fixed after input, adjacency lists are often stored in two arrays instead of linked nodes. An array start of length n+1n + 1 and an array nbr of length mm (or 2m2m undirected): the neighbours of uu are nbr[start[u]] to nbr[start[u+1] - 1]. This compressed form uses Θ(n+m)\Theta(n + m) space and is cache-friendly. Building it needs one pass to count degrees and a prefix sum over the counts.

Worked examples

Worked example 1: list sizes

A directed graph has 8 vertices and 20 arcs; an undirected graph has 8 vertices and 20 edges. How many list nodes do their adjacency lists hold, and how many cells do their adjacency matrices have?

  • Directed: 20 list nodes, one per arc.
  • Undirected: 40 list nodes, two per edge, matching ∑deg⁡=2m=40\sum \deg = 2m = 40.
  • Both matrices have 8×8=648 \times 8 = 64 cells, whatever the edge count.

Worked example 2: walks and triangles from AA

Take vertices 0 to 3 with edges 0-1, 0-2, 1-2, 2-3. Squaring the adjacency matrix gives

A2=(2111121111301101)A^2 = \begin{pmatrix} 2 & 1 & 1 & 1 \\ 1 & 2 & 1 & 1 \\ 1 & 1 & 3 & 0 \\ 1 & 1 & 0 & 1 \end{pmatrix}

  • The diagonal is the degree sequence 2, 2, 3, 1, and its sum is 8=2m8 = 2m.
  • (A2)0,3=1(A^2)_{0,3} = 1: the only walk of length 2 from 0 to 3 goes through 2.
  • (A2)2,3=0(A^2)_{2,3} = 0: there is no common neighbour of 2 and 3.
  • trace(A3)=6\text{trace}(A^3) = 6, so there is 6/6=16 / 6 = 1 triangle, namely {0,1,2}\{0, 1, 2\}.

Worked example 3: edge bounds with components

What is the largest number of edges in a simple undirected graph with 12 vertices and exactly 3 components?

Put 10 vertices in one complete component and leave 2 isolated vertices: (102)=45\binom{10}{2} = 45 edges. Splitting the vertices more evenly only loses edges, since (a2)+(b2)<(a+b−12)+(12)\binom{a}{2} + \binom{b}{2} < \binom{a + b - 1}{2} + \binom{1}{2} whenever both a,b≥2a, b \ge 2. The minimum number of edges with 3 components is 12−3=912 - 3 = 9 (a forest of three trees).

Worked example 4: in-degrees from adjacency lists

int indeg[N] = {0};
for (int u = 0; u < N; u++)
    for (struct edge *e = adj[u]; e != NULL; e = e->next)
        indeg[e->to]++;

The outer loop runs nn times and the inner loop runs once per arc overall, so the total time is Θ(n+m)\Theta(n + m). With an adjacency matrix the same task needs a column sum for every vertex, Θ(n2)\Theta(n^2).

Common traps

  • Counting mm list nodes for an undirected graph instead of 2m2m.
  • Saying a matrix uses Θ(m)\Theta(m) space. It is always Θ(n2)\Theta(n^2).
  • Saying BFS on a matrix is Θ(n+m)\Theta(n + m). It is Θ(n2)\Theta(n^2), because each vertex scans a full row.
  • Confusing walks (repeats allowed) with paths when reading AkA^k.
  • Forgetting the factor 6 when getting triangles from trace(A3)\text{trace}(A^3).
  • Using (n2)\binom{n}{2} for a disconnected graph; the maximum is (n−12)\binom{n-1}{2}.

Quick revision

  • ∑deg⁡(v)=2m\sum \deg(v) = 2m; simple graph: m≤(n2)m \le \binom{n}{2}; tree: m=n−1m = n - 1.
  • Disconnected simple graph: at most (n−12)\binom{n-1}{2} edges; with kk components, at most (n−k+12)\binom{n-k+1}{2}.
  • Matrix: Θ(n2)\Theta(n^2) space, O(1)O(1) edge test, Θ(n)\Theta(n) to list neighbours, traversals Θ(n2)\Theta(n^2).
  • Lists: Θ(n+m)\Theta(n + m) space, 2m2m nodes undirected, traversals Θ(n+m)\Theta(n + m).
  • All in-degrees from lists: Θ(n+m)\Theta(n + m).
  • (Ak)ij(A^k)_{ij} counts walks of length kk; trace(A2)=2m\text{trace}(A^2) = 2m; triangles =trace(A3)/6= \text{trace}(A^3)/6.

Further reading

Test this section