Representing Graphs
From
(→Representation) |
(→Trade-offs) |
||
(17 intermediate revisions not shown) | |||
Line 1: | Line 1: | ||
+ | <noinclude> | ||
+ | {{CS2:BookNav|base=/|up=Contents: CS2|prev=Graph ADTs|next=Variations of Graph ADTs}} | ||
+ | </noinclude> | ||
+ | <br/> | ||
== Adjacency Matrix == | == Adjacency Matrix == | ||
+ | The adjacency matrix of a finite directed or undirected graph G on n vertices is the n × n matrix where the nondiagonal entry aij is the number of edges from vertex i to vertex j, and the diagonal entry aii is either twice the number of loops at vertex i or just the number of loops (usages differ, depending on the mathematical needs; this article follows the former convention for undirected graphs, though directed graphs always follow the latter). There exists a unique adjacency matrix for each graph (up to permuting rows and columns), and it is not the adjacency matrix of any other graph. In the special case of a finite simple graph, the adjacency matrix is a (0,1)-matrix with zeros on its diagonal. If the graph is undirected, the adjacency matrix is symmetric. | ||
- | <br | + | Another matrix representation for a graph is the incidence matrix. |
+ | |||
+ | === Example === | ||
+ | |||
+ | Here is an example of a labeled graph and its adjacency matrix. The convention followed here is that an adjacent edge counts 1 in the matrix for an undirected graph. (X,Y coordinates are 1-6) | ||
+ | |||
+ | [[Image:Graph2.png]]<br> | ||
+ | |||
+ | *The adjacency matrix of a complete graph is all 1's except for 0's on the diagonal. | ||
+ | *The adjacency matrix of an empty graph is all 0's. | ||
+ | |||
+ | <br><br> | ||
== Adjacency List == | == Adjacency List == | ||
Line 8: | Line 24: | ||
<br/><br/> | <br/><br/> | ||
=== Representation === | === Representation === | ||
- | {|class="wikitable" align="left" style="width:18em; background:lightgrey" | + | {|class="wikitable" align="left" border="1" style="width:18em; background:lightgrey" |
|colspan="3"|The graph pictured on the right has this adjacency list representation: | |colspan="3"|The graph pictured on the right has this adjacency list representation: | ||
|- | |- | ||
Line 16: | Line 32: | ||
|- | |- | ||
|c|| adjacent to || a,b | |c|| adjacent to || a,b | ||
- | |} | + | |}<br/> |
If the graph is undirected, every entry is a set of two nodes containing the two ends of the corresponding edge; if it is directed, every entry is a tuple of two nodes, one denoting the source node and the other denoting the destination node of the corresponding arc. Typically, adjacency lists are unordered. | If the graph is undirected, every entry is a set of two nodes containing the two ends of the corresponding edge; if it is directed, every entry is a tuple of two nodes, one denoting the source node and the other denoting the destination node of the corresponding arc. Typically, adjacency lists are unordered. | ||
<br/><br/> | <br/><br/> | ||
Line 25: | Line 41: | ||
One difficulty with the adjacency list structure is that it has no obvious place to store data associated with the edges of a graph, such as the lengths or costs of the edges. To remedy this, some algorithms texts such as that of Goodrich and Tamassia advocate a more object oriented variant of the adjacency list structure, sometimes called an incidence list, which stores for each vertex a list of objects representing the edges incident to that vertex. To complete the structure, each edge must point back to the two vertices forming its endpoints. The extra edge objects in this version of the adjacency list cause it to use more memory than the version in which adjacent vertices are listed directly, but are a convenient location to store additional information about each edge. | One difficulty with the adjacency list structure is that it has no obvious place to store data associated with the edges of a graph, such as the lengths or costs of the edges. To remedy this, some algorithms texts such as that of Goodrich and Tamassia advocate a more object oriented variant of the adjacency list structure, sometimes called an incidence list, which stores for each vertex a list of objects representing the edges incident to that vertex. To complete the structure, each edge must point back to the two vertices forming its endpoints. The extra edge objects in this version of the adjacency list cause it to use more memory than the version in which adjacent vertices are listed directly, but are a convenient location to store additional information about each edge. | ||
<br/><br/> | <br/><br/> | ||
+ | |||
+ | == Trade-offs == | ||
+ | The main alternative to the adjacency list is the adjacency matrix. For a graph with a sparse adjacency matrix an adjacency list representation of the graph occupies less space, because it does not use any space to represent edges that are not present. Using a naive array implementation of adjacency lists on a 32-bit computer, an adjacency list for an undirected graph requires about 8e bytes of storage, where e is the number of edges: each edge gives rise to entries in the two adjacency lists and uses four bytes in each. | ||
+ | <br/><br/> | ||
+ | |||
+ | On the other hand, because each entry in an adjacency matrix requires only one bit, they can be represented in a very compact way, occupying only n^2/8 bytes of contiguous space, where n is the number of vertices. Besides just avoiding wasted space, this compactness encourages locality of reference. | ||
+ | <br/><br/> | ||
+ | |||
+ | Noting that a graph can have at most n^2 edges (allowing loops) we can let d = e/n^2 denote the density of the graph. Then, 8e > n^2/8, or the adjacency list representation occupies more space, precisely when d > 1/64. Thus a graph must be sparse indeed for reduced space to justify an adjacency list representation. However, this analysis is valid only when the representation is intended to store only the connectivity structure of the graph, and not any numerical information about its edges. | ||
+ | <br/><br/> | ||
+ | |||
+ | Besides the space trade-off, the different data structures also facilitate different operations. It is easy to find all vertices adjacent to a given vertex in an adjacency list representation; you simply read its adjacency list. With an adjacency matrix you must instead scan over an entire row, taking O(n) time. If you, instead, want to know if two given vertices have an edge between them, this can be determined at once with an adjacency matrix, while requiring time proportional to the minimum degree of the vertices with the adjacency list. | ||
+ | <br/><br/> | ||
+ | ---- | ||
+ | {{CS2/ChapNav}} | ||
+ | ---- | ||
+ | [[Category:CS2|{{SUBPAGENAME}}]] |
Current revision as of 10:36, 26 May 2009
← Graph ADTs | ↑ Contents: CS2 | Variations of Graph ADTs → |
Contents |
Adjacency Matrix
The adjacency matrix of a finite directed or undirected graph G on n vertices is the n × n matrix where the nondiagonal entry aij is the number of edges from vertex i to vertex j, and the diagonal entry aii is either twice the number of loops at vertex i or just the number of loops (usages differ, depending on the mathematical needs; this article follows the former convention for undirected graphs, though directed graphs always follow the latter). There exists a unique adjacency matrix for each graph (up to permuting rows and columns), and it is not the adjacency matrix of any other graph. In the special case of a finite simple graph, the adjacency matrix is a (0,1)-matrix with zeros on its diagonal. If the graph is undirected, the adjacency matrix is symmetric.
Another matrix representation for a graph is the incidence matrix.
Example
Here is an example of a labeled graph and its adjacency matrix. The convention followed here is that an adjacent edge counts 1 in the matrix for an undirected graph. (X,Y coordinates are 1-6)
- The adjacency matrix of a complete graph is all 1's except for 0's on the diagonal.
- The adjacency matrix of an empty graph is all 0's.
Adjacency List
In graph theory, an adjacency list is the representation of all edges or arcs in a graph as a list.
Representation
The graph pictured on the right has this adjacency list representation: | ||
a | adjacent to | b,c |
b | adjacent to | a,c |
c | adjacent to | a,b |
If the graph is undirected, every entry is a set of two nodes containing the two ends of the corresponding edge; if it is directed, every entry is a tuple of two nodes, one denoting the source node and the other denoting the destination node of the corresponding arc. Typically, adjacency lists are unordered.
In an adjacency list representation, we keep, for each vertex in the graph, all other vertices which it has an edge to (that vertex's "adjacency list"). For instance, the representation suggested by van Rossum, in which a hash table is used to associate each vertex with an array of adjacent vertices, can be seen as an instance of this type of representation, as can the representation in Cormen et al in which an array indexed by vertex numbers points to a singly-linked list of the neighbors of each vertex.
One difficulty with the adjacency list structure is that it has no obvious place to store data associated with the edges of a graph, such as the lengths or costs of the edges. To remedy this, some algorithms texts such as that of Goodrich and Tamassia advocate a more object oriented variant of the adjacency list structure, sometimes called an incidence list, which stores for each vertex a list of objects representing the edges incident to that vertex. To complete the structure, each edge must point back to the two vertices forming its endpoints. The extra edge objects in this version of the adjacency list cause it to use more memory than the version in which adjacent vertices are listed directly, but are a convenient location to store additional information about each edge.
Trade-offs
The main alternative to the adjacency list is the adjacency matrix. For a graph with a sparse adjacency matrix an adjacency list representation of the graph occupies less space, because it does not use any space to represent edges that are not present. Using a naive array implementation of adjacency lists on a 32-bit computer, an adjacency list for an undirected graph requires about 8e bytes of storage, where e is the number of edges: each edge gives rise to entries in the two adjacency lists and uses four bytes in each.
On the other hand, because each entry in an adjacency matrix requires only one bit, they can be represented in a very compact way, occupying only n^2/8 bytes of contiguous space, where n is the number of vertices. Besides just avoiding wasted space, this compactness encourages locality of reference.
Noting that a graph can have at most n^2 edges (allowing loops) we can let d = e/n^2 denote the density of the graph. Then, 8e > n^2/8, or the adjacency list representation occupies more space, precisely when d > 1/64. Thus a graph must be sparse indeed for reduced space to justify an adjacency list representation. However, this analysis is valid only when the representation is intended to store only the connectivity structure of the graph, and not any numerical information about its edges.
Besides the space trade-off, the different data structures also facilitate different operations. It is easy to find all vertices adjacent to a given vertex in an adjacency list representation; you simply read its adjacency list. With an adjacency matrix you must instead scan over an entire row, taking O(n) time. If you, instead, want to know if two given vertices have an edge between them, this can be determined at once with an adjacency matrix, while requiring time proportional to the minimum degree of the vertices with the adjacency list.
CS2: Data Structures
Theory of Computation - ADT Preliminaries
Linear ADTs - Tree ADTs - Graph ADTs - Unordered Collection ADTs