import java.util.NoSuchElementException; import java.util.Iterator; /** Implementation of a Graph data structure. Here we have the ability * to add vertices and edges, check to see if an edge exists, and list all * the neighbors of some vertex. The underlying representation is a 2-D * array for the adjacency matrix. We keep track of the names of the * vertices in a separate array of Vertex objects. * To make the Graph class flexible, we implement it as a weighted graph, * but also provide a constructor without a weight parameter in case the * user wants all the edge weights to be 1 (to have an unweighted graph). */ public class Graph implements GraphInterface { private int numVertices; private int numEdges; private Vertex [] vertex; private int [][] matrix; public Graph() { numVertices = 0; numEdges = 0; vertex = new Vertex[numVertices]; matrix = new int[numVertices][numVertices]; } public void addVertex(Vertex v) { ++numVertices; Vertex [] newVertex = new Vertex[numVertices]; for (int i = 0; i < numVertices - 1; ++i) newVertex[i] = vertex[i]; newVertex[numVertices - 1] = new Vertex(v.getName()); vertex = newVertex; // We also need to expand the adjacency matrix. int [][] newMatrix = new int[numVertices][numVertices]; for (int i = 0; i < numVertices - 1; ++i) for (int j = 0; j < numVertices - 1; ++j) newMatrix[i][j] = matrix[i][j]; // Use -1 to represent no connection to the other existing vertices // And 0 to represent no distance to same vertex. matrix = newMatrix; for (int i = 0; i < numVertices - 1; ++i) { matrix[i][numVertices - 1] = -1; matrix[numVertices - 1][i] = -1; } matrix[numVertices - 1][numVertices - 1] = 0; } // Let's make sure the adjacency matrix is symmetric -- initialize // both the ij and ji elements. public void addEdge(Vertex a, Vertex b) { int i = findVertex(a); int j = findVertex(b); matrix[i][j] = 1; matrix[j][i] = 1; } public void addEdge(Vertex a, Vertex b, int weight) { int i = findVertex(a); int j = findVertex(b); matrix[i][j] = weight; matrix[j][i] = weight; } public int getNumVertices() { return numVertices; } public int getNumEdges() { return numEdges; } // Find which vertices correspond to the strings. Both vertex names // must exist before we can look up if there is an edge connecting them. public boolean edgeExists(Vertex a, Vertex b) { int i = findVertex(a); int j = findVertex(b); return matrix[i][j] > 0; } private int findVertex(Vertex v) { for (int i = 0; i < numVertices; ++i) if (vertex[i].equals(v)) return i; throw new NoSuchElementException(); } public int degree(Vertex v) { int vertexNum = findVertex(v); int count = 0; for (int i = 0; i < numVertices; ++i) if (matrix[vertexNum][i] > 0) ++count; return count; } public String toString() { StringBuilder sb = new StringBuilder(); sb.append("vertices:\n"); for (int i = 0; i < numVertices; ++i) sb.append("\t" + vertex[i] + "\n"); sb.append("\nAdjacency matrix:\n"); for (int i = 0; i < numVertices; ++i) { sb.append("\t"); for (int j = 0; j < numVertices; ++j) sb.append(String.format("%4d", matrix[i][j])); sb.append("\n"); } return sb.toString(); } // Give us a way to find neighboring vertices we're connected to. // startingIndex = row number, the starting place // currentIndex = column number, the next neighbor we'll output class NeighborIterator implements Iterator { int startingIndex; int currentIndex; // constructor needs to know which vertex we start from public NeighborIterator(Vertex v) { startingIndex = findVertex(v); // begin the currentIndex at the first column in the matrix // that has a non-zero value in this row. If there isn't any, // then currentIndex will point to the end of the row. for (currentIndex = 0; currentIndex < numVertices; ++currentIndex) if (matrix[startingIndex][currentIndex] > 0) break; } public boolean hasNext() { return currentIndex < numVertices; } // Return the vertex pointed to by currentIndex, and then advance // currentIndex to the next neighbor or to the end of the row. public Object next() { if (! hasNext()) throw new NoSuchElementException(); Object retVal = vertex[currentIndex]; for (++currentIndex; currentIndex < numVertices; ++currentIndex) if (matrix[startingIndex][currentIndex] > 0) break; return retVal; } public void remove() { throw new UnsupportedOperationException(); } } // Now, let's give a user class a way of creating an iterator based // from one vertex. public Iterator neighborIterator(Vertex v) { return new NeighborIterator(v); } }