package berack96.lib.graph.impl;
import berack96.lib.graph.Edge;
import berack96.lib.graph.Graph;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Graph that uses HashMap for vertices and edges
* More specifically it utilizes a Map containing all the vertices mapped to all their edges
* Technically this version of the graph combine the fast adding/removing of the edges of the Matrix implementation,
* with the low memory and fast adding/removing of vertices of the Linked List implementation.
* This happen if the HashMap is not reallocated. So in the end each operation of adding or removing has O(n)
*
* @param the vertices
* @param the weight of the edges
* @author Berack96
*/
public class MapGraph extends AGraph {
/**
* Map that contains the edges from a vertex to another
* The first vertex is the vertex where start the edge, the second one is where the edge goes
* If an edge exist, then it's weight is returned
*/
private final Map> edges = new HashMap<>();
@Override
public Iterator iterator() {
return edges.keySet().iterator();
}
@Override
protected Graph getNewInstance() {
return new MapGraph<>();
}
@Override
protected void addVertex(V vertex) {
edges.put(vertex, new HashMap<>());
}
@Override
protected boolean containsVertex(V vertex) {
return edges.containsKey(vertex);
}
@Override
protected void removeVertex(V vertex) {
edges.remove(vertex);
edges.forEach((v, map) -> map.remove(vertex));
}
@Override
protected void removeAllVertices() {
edges.clear();
}
@Override
protected boolean containsEdgeImpl(V vertex1, V vertex2) {
return contains(vertex1) && contains(vertex2) && edges.get(vertex1).containsKey(vertex2);
}
@Override
protected W addEdgeImpl(V vertex1, V vertex2, W weight) {
return edges.get(vertex1).put(vertex2, weight);
}
@Override
protected W getWeightImpl(V vertex1, V vertex2) {
return edges.get(vertex1).get(vertex2);
}
@Override
protected Collection> getEdgesOutImpl(V vertex) {
Collection> collection = new HashSet<>();
edges.get(vertex).forEach((dest, weight) -> collection.add(new Edge<>(vertex, dest, weight)));
return collection;
}
@Override
protected Collection> getEdgesInImpl(V vertex) {
Collection> collection = new HashSet<>();
edges.forEach((source, edge) -> {
if (edge.get(vertex) != null)
collection.add(new Edge<>(source, vertex, edge.get(vertex)));
});
return collection;
}
@Override
protected void removeEdgeImpl(V vertex1, V vertex2) {
edges.get(vertex1).remove(vertex2);
}
@Override
protected void removeAllOutEdgeImpl(V vertex) {
edges.put(vertex, new HashMap<>());
}
@Override
protected void removeAllInEdgeImpl(V vertex) {
edges.forEach((v, map) -> map.remove(vertex));
}
@Override
public int size() {
return edges.size();
}
@Override
public int numberOfEdges() {
AtomicInteger sum = new AtomicInteger(0);
edges.forEach((v, map) -> sum.getAndAdd(map.size()));
return sum.get();
}
}