Since there is so much variability in types of graphs and how they are used, most standard collection libraries don’t include a Graph implementation. Here is a sample ADT described as a Java interface:
/**
* Minimal Unweighted Graph Interface.
* This interface assumes that the graph size is known at initialization time.
* Each node has an integer identifier.
* No self-edges are allowed.
*/
public interface Graph<T> {
void init(int numNodes);
int numNodes();
int numEdges();
void addEdge(int from, int to);
boolean hasEdge(int from, int to);
void removeEdge(int from, int to);
Iterable<Integer> neighbors(int id);
}
Performance?
Memory requirements?
Performance?
Memory requirements? \(\Theta(V^2)\)
Performance?
Memory requirements?
Performance?
Memory requirements: \(\Theta(V + E)\), where \(V\) is the number of vertices and \(E\) is the number of edges.
Adjacency HashSets
Performance?
Memory requirements? \(\Theta(V + E)\)
Recursive:
RecursiveDFS(currentV) {
if ( currentV is not in visitedSet ) {
Add currentV to visitedSet
"Visit" currentV
for each vertex adjV adjacent to currentV {
RecursiveDFS(adjV)
}
}
}
Non-Recursive:
DFS(startV) {
Push startV to stack
while ( stack is not empty ) {
currentV = Pop stack
if ( currentV is not in visitedSet ) {
"Visit" currentV
Add currentV to visitedSet
for each vertex adjV adjacent to currentV
Push adjV to stack
}
}
}
BFS(startV) {
Enqueue startV in frontierQueue
Add startV to discoveredSet
while ( frontierQueue is not empty ) {
currentV = Dequeue from frontierQueue
"Visit" currentV
for each vertex adjV adjacent to currentV {
if ( adjV is not in discoveredSet ) {
Enqueue adjV in frontierQueue
Add adjV to discoveredSet
}
}
}
}
Example: