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
Vocabulary
A graph has a set of vertices and a set of edges . Write and .
- Undirected: an edge has no direction. Directed: an edge goes from to .
- Simple graph: no self-loops and no parallel edges. GATE assumes simple graphs unless it says otherwise.
- Weighted: each edge carries a number.
- Degree : number of edges at . 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 edges; equivalently acyclic with 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: in an undirected graph. So the number of odd-degree vertices is even.
- In a directed graph, .
- A simple undirected graph has at most edges; a simple directed graph at most .
- The number of distinct simple undirected graphs on labelled vertices is .
- A forest with vertices and components has edges.
- A graph with vertices and components has at least edges, and at most edges (one big complete component plus isolated vertices).
- The largest disconnected simple graph on vertices has edges. Any simple graph with more edges is connected.
- A complete bipartite graph has edges.
Representations
Adjacency matrix
An matrix with if there is an edge from to (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 regardless of .
- Edge test .
- Listing the neighbours of : , a full row.
- For an undirected graph the matrix is symmetric, and the diagonal is zero for a simple graph.
- Row sum of row is the out-degree of ; column sum of column is the in-degree of .
Adjacency list
An array of lists; the list of holds every with an edge .
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 . An undirected edge appears in two lists, so there are list nodes; a directed graph has .
- Edge test : .
- Listing the neighbours of : .
- Out-degree of is the length of its list. In-degree needs a pass over all lists: for all vertices at once.
Edge list and incidence matrix
- Edge list: an array of pairs (or triples with weights). Space . Natural input for Kruskal's algorithm, which sorts edges.
- Incidence matrix: , with entry when vertex is an end of edge . In an undirected graph every column has exactly two 1s; for a directed graph one end is marked and the other . Space .
Choosing a representation
| Task | Adjacency matrix | Adjacency list |
|---|---|---|
| Space | ||
| Is an edge? | ||
| Visit all neighbours of | ||
| BFS or DFS of the whole graph | ||
| Add an edge | at the list head | |
| Remove an edge | ||
| Transpose (reverse all edges) |
Since , lists are never worse than the matrix for traversals. Use a matrix for dense graphs ( close to ), 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 (entries 0 or 1),
because counts the middle vertices with edges to and to , and the argument extends by induction.
Useful specialisations for a simple undirected graph:
- , since a closed walk of length 2 goes to a neighbour and back.
- .
- (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 and an array nbr of length (or undirected): the neighbours of are nbr[start[u]] to nbr[start[u+1] - 1]. This compressed form uses 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 .
- Both matrices have cells, whatever the edge count.
Worked example 2: walks and triangles from
Take vertices 0 to 3 with edges 0-1, 0-2, 1-2, 2-3. Squaring the adjacency matrix gives
- The diagonal is the degree sequence 2, 2, 3, 1, and its sum is .
- : the only walk of length 2 from 0 to 3 goes through 2.
- : there is no common neighbour of 2 and 3.
- , so there is triangle, namely .
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: edges. Splitting the vertices more evenly only loses edges, since whenever both . The minimum number of edges with 3 components is (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 times and the inner loop runs once per arc overall, so the total time is . With an adjacency matrix the same task needs a column sum for every vertex, .
Common traps
- Counting list nodes for an undirected graph instead of .
- Saying a matrix uses space. It is always .
- Saying BFS on a matrix is . It is , because each vertex scans a full row.
- Confusing walks (repeats allowed) with paths when reading .
- Forgetting the factor 6 when getting triangles from .
- Using for a disconnected graph; the maximum is .
Quick revision
- ; simple graph: ; tree: .
- Disconnected simple graph: at most edges; with components, at most .
- Matrix: space, edge test, to list neighbours, traversals .
- Lists: space, nodes undirected, traversals .
- All in-degrees from lists: .
- counts walks of length ; ; triangles .