A graph G=(V,E) models pairwise relationships between a set of vertices V and a set of edges E. Two representations recur throughout: the adjacency matrix, a V×V 0/1 (or weight) matrix, and the adjacency list, an array of V lists where list i holds every vertex adjacent to i.
Conventions used throughout these notes (assume them unless a question says otherwise): V and E also denote the number of vertices and edges; graphs are simple (no self-loops or parallel edges); an undirected edge is stored in both endpoints' adjacency lists; complexities are worst case and assume adjacency lists unless stated; logarithms are base 2 (the base does not change an O-bound); for unweighted graphs, distance means number of edges.
SPACE COST OF THE TWO REPRESENTATIONS
Adjacency matrix: O(V2) space,Adjacency list: O(V+E) space
Use the matrix when the graph is dense (E close to V^2) or constant-time edge checks are needed; use the list when the graph is sparse (E much smaller than V^2). An undirected graph's adjacency lists hold 2E entries in total (each edge appears in both endpoints' lists); a directed graph's hold E.
HANDSHAKE LEMMA AND EDGE BOUNDS (SIMPLE GRAPHS)
v∈V∑deg(v)=2E,E≤2V(V−1) (undirected),E≤V(V−1) (directed)
The degree sum counts every undirected edge once from each end. Consequence: every undirected graph has an even number of odd-degree vertices. In a directed graph, the sum of in-degrees = the sum of out-degrees = E.
A short C implementation of BFS, with each vertex's neighbours kept in a row of a 2-D array and a plain array as the queue:
#define MAXV 100
int adj[MAXV][MAXV]; /* adj[u][0] = degree of u, adj[u][1..deg] = its neighbours */
int dist[MAXV], visited[MAXV];
void bfs(int s, int V) {
int queue[MAXV], front = 0, rear = 0;
for (int i = 0; i < V; i++) {
visited[i] = 0;
dist[i] = -1;
}
visited[s] = 1;
dist[s] = 0;
queue[rear++] = s;
while (front < rear) {
int u = queue[front++];
int deg = adj[u][0];
for (int i = 1; i <= deg; i++) {
int v = adj[u][i];
if (!visited[v]) {
visited[v] = 1;
dist[v] = dist[u] + 1;
queue[rear++] = v;
}
}
}
}
The code numbers vertices 0 to V-1. To run it on the worked example (vertices 1 to 5), store each row's neighbours in increasing order and call bfs(1, 6). Slot 0 is never reached, so dist[0] stays −1. The dequeue order is 1, 2, 3, 4, 5, and dist[1] to dist[5] are 0, 1, 1, 2, 3. Each vertex enters the queue at most once, so a queue of MAXV slots never overflows. The running time is O(V+E) because only the deg(u) filled slots of each row are scanned, although the array itself reserves MAXV × MAXV ints.