Storing graphs#
Adjacency matrix#
When storing a graph in an adjacency matrix we have a matrix that is
So for a weighted graph we use int[][] G = new int[n][n]
where the value stored at G[x][y]
corresponds to the weight from vertex Integer.MAX_VALUE
or we use an Integer array and set it to null.
If the graph is unweighted we can either use the same 2D int array and just store all edge weights as 1 or we can use a 2D boolean array which interestingly does use less space in java. A normal boolean variable uses 32 bits in java just like an int however in an array each boolean value only takes up 8 bits.
If the graph is undirected then [x][y] and [y][x]
.
The biggest problem with storing graphs this way is that
public class UndirectedUnweightedGraph {
private final boolean[][] adjMatrix;
public final int n;
public GraphI(int numNodes) {
if (numNodes < 1) throw new IllegalArgumentException();
this.adjMatrix = new boolean[numNodes][numNodes];
this.n = numNodes;
}
public boolean addEdge(int u, int v){
if(0<= u && u<n && 0 <= v && v<n){
if(adjMatrix[u][v]) return false;
adjMatrix[u][v] = adjMatrix[v][u] = true;
return true;
}
throw new IndexOutOfBoundsException();
}
}
Edge table#
An other easy but less common alternative to the adjacency matrix is a list or table of edges. With edges having the following structure
class Edge {
int from, to, weight;
}
The nice things about this solution is that it only uses memory of
Adjacency list#
In an adjacency list we store all edges that are connected to a certain vertex. We then have a list of adjacency lists for the entire graph. And adjacency list can be just a simple array but is also often seen as a linked list due to being dynamic. If the graph is undirected an edge appears in both adjacency lists. This structure only uses
public class UnweightedGraph<K> {
private static class Vertex<K> {
K data;
int indegree = 0, deg;
boolean visited;
List<Vertex<K>> adjList = new LinkedList<Vertex<K>>();
Vertex(K value) {
data = value;
}
boolean addEdgeTo(Vertex<K> to) {
return (adjList.contains(to)) ? false : adjList.add(to);
}
}
private Map<K, Vertex<K>> vertices;
private int nofEdges = 0;
public AdjListGraph() { // default constructor
this(false);
}
public AdjListGraph(boolean directed) {
super(directed);
vertices = new HashMap<K, Vertex<K>>();
}
public AdjListGraph(AdjListGraph<K> orig) { // copy constructor
this(orig.isDirected());
for (K k : orig.vertices.keySet()) {
addVertex(k);
}
for (Vertex<K> v : orig.vertices.values()) {
for (Vertex<K> w : v.adjList) {
addEdge(v.data, w.data);
}
}
}
public boolean addVertex(K vertex) {
if (vertex != null && !vertices.containsKey(vertex)) {
vertices.put(vertex, new Vertex<K>(vertex));
return true;
} else {
return false;
}
}
public boolean addEdge(K from, K to) {
Vertex<K> vf = vertices.get(from);
Vertex<K> vt = vertices.get(to);
if (vf != null && vt != null && vf.addEdgeTo(vt)) {
vt.indegree++;
if (!isDirected()) {
vt.addEdgeTo(vf);
vf.indegree++;
}
nofEdges++;
return true;
} else {
return false;
}
}
}