<style> .reveal-up, .reveal-left, .reveal-right, .reveal-stagger > * { opacity: 1 !important; transform: none !important; } </style>
  1. Learn
  2. DSA
  3. Graphs
All lessons in this course

Lesson 31 of 50 14 minAdvanced

Graphs and how to store them

Learn what a graph is (vertices, edges, directed, weighted, cycles), where graphs appear in real software, and how to store one as an adjacency list, an adjacency matrix or an edge list.

A tree has one root and every node has one parent. Many real networks are messier: roads connect places in loops, a task can depend on several other tasks, a beam is connected to two columns and three secondary beams. A graph is the general model for “things and the connections between them”, and the rest of this module is about the algorithms that work on it.

The vocabulary

TermMeaning
Vertex (node)A thing: a place, a task, a beam, a web page
EdgeA connection between two vertices
Undirected / directedA two-way road vs a one-way street (“A depends on B” is directed)
WeightedEach edge has a number: distance, time, cost, capacity
DegreeNumber of edges at a vertex (directed: in-degree and out-degree)
PathA sequence of vertices joined by edges
CycleA path that returns to where it started
ConnectedEvery vertex can reach every other one
DAGDirected acyclic graph: directed, with no cycles (dependencies, schedules)
V and EThe number of vertices and of edges, used in every complexity formula

A tree is just a special graph: connected, with no cycles, and exactly V − 1 edges.

Graphs are everywhere: road and rail networks, the internet, project dependencies in a .NET solution, task schedules, social networks, electrical circuits, pipe networks, and the connections between elements in a structural model.

Interactive

One graph, two ways to store it

Seven places on a site (A = gate, B = store, C = crane, D = office, E = yard, F = batching plant, G = workshop) and the roads between them. Click a place.

42365234716ABCDEFG
Adjacency list
A → B (4), D (2)
B → A (4), C (6), E (3)
C → B (6), E (2), F (3)
D → A (2), E (5), G (7)
E → B (3), C (2), D (5), F (6), G (4)
F → C (3), E (6), G (1)
G → D (7), E (4), F (1)
Adjacency matrix (weight, · = none)
ABCDEFG
A·4·2···
B4·6·3··
C·6··23·
D2···5·7
E·325·64
F··3·6·1
G···741·
E (Yard): degree 5. In the list, its neighbours are ready to read: 5 entries. In the matrix you scan a row of 7 cells, but “is there a road E→X?” is one cell lookup. Storage: the list holds 22 entries (2E), the matrix 49 cells (V²).

Adjacency list: each vertex knows its neighbours

The most common representation: for every vertex, a list of its neighbours (with weights if needed). It uses memory proportional to V + E and lists a vertex’s neighbours directly, which is exactly what most algorithms need.

AdjacencyList.cs
var roads = new Dictionary<string, List<(string To, int Minutes)>>(); void AddRoad(string a, string b, int minutes){    if (!roads.ContainsKey(a)) roads[a] = new();    if (!roads.ContainsKey(b)) roads[b] = new();    roads[a].Add((b, minutes));          // undirected: store both directions    roads[b].Add((a, minutes));} AddRoad("Gate", "Store", 4);AddRoad("Gate", "Office", 2);AddRoad("Store", "Yard", 3);AddRoad("Office", "Yard", 5); foreach (var (place, list) in roads)    Console.WriteLine($"{place}: {string.Join(", ", list.Select(r => $"{r.To} ({r.Minutes})"))}"); Console.WriteLine($"Degree of Yard: {roads["Yard"].Count}");
Output
Gate: Store (4), Office (2)
Store: Gate (4), Yard (3)
Office: Gate (2), Yard (5)
Yard: Store (3), Office (5)
Degree of Yard: 2

Algorithms usually number the vertices 0 to V − 1 and use an array of lists, which is faster than a dictionary of strings. Keep a separate string[] names if you need the labels back.

Adjacency matrix: a V × V table

m[i, j] holds 1 (or the weight) if there is an edge from i to j. Checking one particular connection is O(1), but the table always uses V² cells, even when there are few edges, and listing the neighbours of a vertex means scanning a whole row.

ListAndMatrix.cs
int n = 5;int[][] edges = { new[] { 0, 1 }, new[] { 0, 2 }, new[] { 1, 3 }, new[] { 2, 3 }, new[] { 3, 4 } }; var adj = new List<int>[n];                     // adjacency listfor (int i = 0; i < n; i++) adj[i] = new List<int>();var matrix = new bool[n, n];                    // adjacency matrix foreach (var e in edges){    adj[e[0]].Add(e[1]); adj[e[1]].Add(e[0]);    matrix[e[0], e[1]] = matrix[e[1], e[0]] = true;} for (int i = 0; i < n; i++)    Console.WriteLine($"{i}: {string.Join(" ", adj[i])}");Console.WriteLine(matrix[3, 4]);                // is there an edge 3-4? O(1)Console.WriteLine(matrix[0, 4]);
Output
0: 1 2
1: 0 3
2: 0 3
3: 1 2 4
4: 3
True
False
Adjacency listAdjacency matrixEdge list
MemoryO(V + E)O(V²)O(E)
Is there an edge u–v?O(degree of u)O(1)O(E)
All neighbours of uO(degree of u)O(V)O(E)
Best forMost graphs (sparse)Small or very dense graphsAlgorithms that just loop over edges (Kruskal, Bellman-Ford)

Graphs you never build

Sometimes the graph is implicit: you compute the neighbours when you need them. A grid is a graph where each cell’s neighbours are the cells above, below, left and right. A puzzle is a graph where each state’s neighbours are the states one move away. You will see this in the BFS lesson.

Quick check

An undirected graph has 11 edges. How many entries does its adjacency list hold in total?

Quick check

Which representation would you choose for a city map with 200,000 junctions?

Practice

Construction dependencies are given as (before, after) pairs. Compute the in-degree (number of prerequisites) of every task and print the tasks that can start immediately (in-degree 0), in the order they first appear. Pairs: Survey→Excavate, Excavate→Footings, Order steel→Fabricate, Fabricate→Columns, Footings→Columns.

Show a hint

Use a Dictionary<string, int>. For each pair, make sure the first task exists with TryAdd(task, 0), and add 1 to the second task.

Show the solution
Solution.cs
var deps = new (string Before, string After)[]{    ("Survey", "Excavate"), ("Excavate", "Footings"), ("Order steel", "Fabricate"),    ("Fabricate", "Columns"), ("Footings", "Columns")}; var inDegree = new Dictionary<string, int>();foreach (var (a, b) in deps){    inDegree.TryAdd(a, 0);    inDegree[b] = inDegree.GetValueOrDefault(b) + 1;} foreach (var (task, d) in inDegree)    Console.WriteLine($"{task}: {d}"); var starts = inDegree.Where(p => p.Value == 0).Select(p => p.Key);Console.WriteLine("Can start now: " + string.Join(", ", starts));
Output
Survey: 0
Excavate: 1
Footings: 1
Order steel: 0
Fabricate: 1
Columns: 2
Can start now: Survey, Order steel

Remember

  • A graph is vertices plus edges; edges can be directed and/or weighted.
  • Adjacency lists use O(V + E) memory and list neighbours fast: the default choice.
  • An adjacency matrix answers “is there an edge?” in O(1) but costs O(V²) memory.
  • Grids and puzzles are implicit graphs: compute neighbours on the fly.
0 of 50 lessons completed