What is better, adjacency lists or adjacency matrix, for graph problems in C++? What are the advantages and disadvantages of each?
To add to keyser5053's answer about memory usage.
For any directed graph, an adjacency matrix (at 1 bit per edge) consumes n^2 * (1)
bits of memory.
For a complete graph, an adjacency list (with 64 bit pointers) consumes n * (n * 64)
bits of memory, excluding list overhead.
For an incomplete graph, an adjacency list consumes 0
bits of memory, excluding list overhead.
For an adjacency list, you can use the follow formula to determine the maximum number of edges (e
) before an adjacency matrix is optimal for memory.
edges = n^2 / s
to determine the maximum number of edges, where s
is the pointer size of the platform.
If you're graph is dynamically updating, you can maintain this efficiency with an average edge count (per node) of n / s
.
Some examples with 64 bit pointers and dynamic graph (A dynamic graph updates the solution of a problem efficiently after changes, rather than recomputing it from scratch each time after a change has been made.)
For a directed graph, where n
is 300, the optimal number of edges per node using an adjacency list is:
= 300 / 64
= 4
If we plug this into keyser5053's formula, d = e / n^2
(where e
is the total edge count), we can see we are below the break point (1 / s
):
d = (4 * 300) / (300 * 300)
d < 1/64
aka 0.0133 < 0.0156
However, 64 bits for a pointer can be overkill. If you instead use 16bit integers as pointer offsets, we can fit up to 18 edges before breaking point.
= 300 / 16
= 18
d = ((18 * 300) / (300^2))
d < 1/16
aka 0.06 < 0.0625
Each of these examples ignore the overhead of the adjacency lists themselves (64*2
for a vector and 64 bit pointers).