Represent an undirected graph as a per-vertex list of neighbours. For every edge (u, v), append v to adj[u] and u to adj[v]. Neighbour lists keep insertion order so the graph is a stable, deterministic fixture for the search lessons.

Algorithm

The canonical fixture is 6 vertices [1..6] with undirected edges (1,2), (1,3), (2,4), (3,4), (4,5), (5,6) inserted in that order. The final adjacency list is {1: [2, 3], 2: [1, 4], 3: [1, 4], 4: [2, 3, 5], 5: [4, 6], 6: [5]}. This same graph drives graph-bfs, graph-dfs, and graph-shortest-path-bfs.

adjacency list Each edge adds two directed entries, one in each direction.

Visual walkthrough

The graph fixture is pinned once, then the adjacency list writes each undirected edge in both directions.

Step 1 - Pinned graph fixture

The six vertices and six undirected edges are the shared fixture for BFS and DFS.

Graph with edges (1,2), (1,3), (2,4), (3,4), (4,5), (5,6).123456

Step 2 - Final adjacency list

Each row lists neighbours in the same insertion order used by the lesson.

Adjacency list after all six undirected edges are inserted.vertexneighbours1[2, 3]2[1, 4]3[1, 4]4[2, 3, 5]5[4, 6]6[5]

Basic Implementation

basic.ts
const edges: [number, number][] = [[1, 2], [1, 3], [2, 4], [3, 4], [4, 5], [5, 6]];
const adj: Map<number, number[]> = new Map();
for (const [u, v] of edges) {
    if (!adj.has(u)) adj.set(u, []);
    if (!adj.has(v)) adj.set(v, []);
    adj.get(u)!.push(v);
    adj.get(v)!.push(u);
}
const parts: string[] = [];
for (const [v, nbrs] of adj) {
    parts.push(`${v}: [${nbrs.join(", ")}]`);
}
console.log("{" + parts.join(", ") + "}");

Complexity

  • Build: O(V + E)
  • Space: O(V + E)

Implementation notes

  • TypeScript: a typed Map<number, number[]> preserves insertion order; each value is an array of neighbours.
  • The replay shows the adjacency list after each edge is added, matching the lesson spec.