An adjacency matrix is a way of representing an vertex graph by an matrix, , whose entries are boolean values.
int n; bool **a;
The matrix entry is defined as
With this representation, the , , and operations just involve setting or reading the matrix entry :
void addEdge(int i, int j) { a[i][j] = true; } void removeEdge(int i, int j) { a[i][j] = false; } bool hasEdge(int i, int j) { return a[i][j]; }These operations clearly take constant time per operation.
|
Where the adjacency matrix performs poorly is with the and operations. To implement these, we must scan all entries in the corresponding row or column of and gather up all the indices, , where , respectively , is true.
void outEdges(int i, List &edges) { for (int j = 0; j < n; j++) if (a[i][j]) edges.add(j); } void inEdges(int i, List &edges) { for (int j = 0; j < n; j++) if (a[j][i]) edges.add(j); }These operations clearly take time per operation.
Another drawback of the adjacency matrix representation is that it is big. It stores an boolean matrix, so it requires at least bits of memory. The implementation here uses a matrix of values so it actually uses on the order of bytes of memory. A more careful implementation, that packs boolean values into each word of memory could reduce this space usage to words of memory.
Despite the high memory usage and poor performance of the and operations, an can still be useful for some applications. In particular, when the graph is dense, i.e., it has close to edges, then a memory usage of may be acceptable.
The data structure is also commonly used because algebraic operations on the matrix can be used to efficiently compute properties of the graph . This is a topic for a course on algorithms, but we point out one such property here: If we treat the entries of as integers (1 for and 0 for ) and multiply by itself using matrix multiplication then we get the matrix . Recall, from the definition of matrix multiplication, that
opendatastructures.org