package graphutils; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.NoSuchElementException; import misc.MultiHashMap; public abstract class AbstractGraph<V, E extends Edge<V>> { private List<V> vertices; private MultiHashMap<V, E> outNeighborhood; public AbstractGraph() { vertices = new LinkedList<V>(); outNeighborhood = new MultiHashMap<V, E>(); } public Iterator<V> iterator() { return getVertices().iterator(); } public List<V> getVertices() { return vertices; } public List<E> getEdges() { List<E> edges = new LinkedList<E>(); for (V vertex : getVertices()) { for (E edge : outgoingEdges(vertex)) { edges.add(edge); } } return edges; } public List<E> outgoingEdges(V src) { failIfNotContained(src); List<E> list = outNeighborhood.get(src); return list != null ? list : new LinkedList<E>(); } public boolean isConnected(V src, V dst) { for (Edge<V> e : outgoingEdges(src)) { if (e.getDestination().equals(dst)) { return true; } } return false; } public int outDegree(V vertex) { return outgoingEdges(vertex).size(); } public boolean contains(V vertex) { return vertices.contains(vertex); } public boolean isEmpty() { return size() == 0; } public int size() { return vertices.size(); } public int numberOfEdges() { return outNeighborhood.totalSize(); } public boolean addVertex(V vertex) { if (!contains(vertex)) { vertices.add(vertex); return true; } return false; } public void removeVertex(V vertex) { removeEdgesFrom(vertex); removeEdgesTo(vertex); vertices.remove(vertex); } public void addEdge(E edge) { failIfNotContained(edge.getSource()); failIfNotContained(edge.getDestination()); outNeighborhood.add(edge.getSource(), edge); } public void removeEdge(E edge) { removeEdge(edge.getSource(), edge.getDestination()); } public void removeEdge(V src, V dst) { List<E> edges = outNeighborhood.get(src); Iterator<E> it = edges.iterator(); E edge; while (it.hasNext()) { edge = it.next(); if (edge.getDestination() == dst) { it.remove(); } } } public void removeEdgesFrom(V source) { outNeighborhood.removeAll(source); } public void removeEdgesTo(V destination) { Iterator<V> sourceIterator = outNeighborhood.getKeySetIterator(); while (sourceIterator.hasNext()) { V source = sourceIterator.next(); Iterator<E> edgeIterator = outgoingEdges(source).iterator(); while (edgeIterator.hasNext()) { E edge = edgeIterator.next(); if (edge.getDestination().equals(destination)) { edgeIterator.remove(); } } } } public void failIfNotContained(V vertex) { if (!contains(vertex)) { throw new NoSuchElementException("Graph has no such vertex : " + vertex); } } @Override public String toString() { String res = "Graph with " + size() + " vertices and " + numberOfEdges() + " edges:\n"; for (V vertex : getVertices()) { res += vertex.toString() + '\n'; for (E edge : outgoingEdges(vertex)) { res += edge.toString() + '\n'; } } return res; } }