diff --git a/.gitignore b/.gitignore
index 786237e..689f042 100644
--- a/.gitignore
+++ b/.gitignore
@@ -125,8 +125,9 @@ local.properties
# mine
+target/
.idea/*
.project
*.iml
-.classpath
-/.gradle/
+.classpath
+/.gradle/
diff --git a/build.gradle b/build.gradle
deleted file mode 100644
index 58ef372..0000000
--- a/build.gradle
+++ /dev/null
@@ -1,32 +0,0 @@
-apply plugin: 'java'
-apply plugin: 'eclipse'
-
-version='1.0-SNAPSHOT'
-
-jar {
- manifest {
- attributes 'Main-Class': 'berack96.lib.graph.view.Main'
- }
- from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
-}
-
-test {
- useJUnitPlatform()
-}
-
-sourceSets.main.java {
- srcDirs "src"
- srcDirs "test"
-}
-
-repositories {
- mavenCentral()
-}
-
-dependencies {
- implementation 'org.junit.jupiter:junit-jupiter:5.5.2'
- compile group: 'com.google.code.gson', name: 'gson', version: '2.8.5'
-
- /*compile group: 'commons-collections', name: 'commons-collections', version: '3.2'*/
- testCompile 'junit:junit:5.5.2'
-}
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..5cfc0ad
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,80 @@
+
+
+ 4.0.0
+
+ berack96
+ Graph
+ 1.0-SNAPSHOT
+
+
+ org.junit.jupiter
+ junit-jupiter-api
+ 5.9.0
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter-params
+ 5.9.0
+ test
+
+
+ com.google.code.gson
+ gson
+ 2.9.1
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+ 2.2
+
+
+ org.apache.maven.plugins
+ maven-assembly-plugin
+ 2.2
+
+
+ jar-with-dependencies
+
+
+
+ berack96.lib.graph.view.Main
+
+
+
+
+
+ package
+
+ single
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+
+
+ attach-javadocs
+ prepare-package
+
+ jar
+
+
+
+
+
+
+
+ 17
+ 17
+
+
+
\ No newline at end of file
diff --git a/src/berack96/lib/graph/Edge.java b/src/main/java/berack96/lib/graph/Edge.java
similarity index 100%
rename from src/berack96/lib/graph/Edge.java
rename to src/main/java/berack96/lib/graph/Edge.java
diff --git a/src/berack96/lib/graph/Graph.java b/src/main/java/berack96/lib/graph/Graph.java
similarity index 86%
rename from src/berack96/lib/graph/Graph.java
rename to src/main/java/berack96/lib/graph/Graph.java
index 7d58ece..a6c93e5 100644
--- a/src/berack96/lib/graph/Graph.java
+++ b/src/main/java/berack96/lib/graph/Graph.java
@@ -1,638 +1,669 @@
-package berack96.lib.graph;
-
-import berack96.lib.graph.visit.VisitStrategy;
-import berack96.lib.graph.visit.impl.BFS;
-import berack96.lib.graph.visit.impl.Dijkstra;
-import berack96.lib.graph.visit.impl.VisitInfo;
-
-import java.util.*;
-import java.util.function.Consumer;
-
-/**
- * An abstract class for the graphs.
- * This class is used for the graphs in general.
- * There are more specific {@link GraphDirected} and {@link GraphUndirected} edges graph interfaces.
- *
- * @param The Object that represent a vertex
- * @author Berack96
- */
-public abstract class Graph implements Iterable {
-
- public static final int NO_EDGE = 0;
- public final static String NOT_CONNECTED = "The source vertex doesn't have a path that reach the destination";
- public final static String PARAM_NULL = "The parameter must not be null";
- public final static String VERTEX_NOT_CONTAINED = "The vertex must be contained in the graph";
-
- /**
- * Map that contains the vertex as key and a set of all the marker associated with it.
- */
- private final Map> markers = new HashMap<>();
-
- /**
- * Get a new instance of this Graph.
- *
- * @return A new instance of the graph
- */
- protected abstract Graph getNewInstance();
-
- /**
- * Check if the vertex passed is contained in the graph or not.
- * The vertex V1 is contained in the graph G, if and only if:
- * exist V2 in G such that V2 == V1
- *
- * @param vertex the vertex to check
- * @return true if the vertex is contained, false otherwise
- */
- public abstract boolean contains(V vertex) throws NullPointerException;
-
- /**
- * Get an instance of the vertex linked with this graph.
- * For more info see {@link Vertex}
- *
- * @param vertex the vertex
- * @return a vertex
- * @throws IllegalArgumentException if the vertex is not contained in the graph
- */
- public final Vertex get(V vertex) throws IllegalArgumentException {
- checkVert(vertex);
- return new Vertex<>(this, vertex);
- }
-
- /**
- * Add the vertex to the graph. If it's already in the graph it will be replaced and all its edges will be reset.
- * Of course the vertex added will have no marks nor edge to any other vertex nor form any other vertex.
- *
- * @param vertex the vertex to add
- * @throws NullPointerException if the vertex is null
- */
- public abstract void add(V vertex) throws NullPointerException;
-
- /**
- * Add the specified vertex to the graph only if the graph doesn't contains it.
- * The graph contains a vertex only if the method {@link #contains(Object)} returns true.
- *
- * @param vertex the vertex to add
- * @return true if it adds a vertex, false if it was already in the graph
- * @throws NullPointerException if the vertex is null
- */
- public final boolean addIfAbsent(V vertex) throws NullPointerException {
- if (contains(vertex))
- return false;
- add(vertex);
- return true;
- }
-
- /**
- * Add all the vertices contained in the collection to the graph.
- * If a vertex is contained in the collection and in the graph is ignored and it will not be replaced.
- * Null vertices will be ignored and they will not be added to the graph.
- *
- * @param vertices a collection of the vertices to add
- * @throws NullPointerException if the set is null
- */
- public void addAll(@SuppressWarnings("ConstantConditions") Collection vertices) throws NullPointerException {
- check(vertices);
- for (V vertex : vertices)
- addIfAbsent(vertex);
- }
-
- /**
- * Remove the selected vertex from the graph.
- * After this method's call the vertex will be no longer present in the graph, and nether all his edges and marks.
- *
- * @param vertex the vertex to remove
- * @throws NullPointerException if the vertex is null
- * @throws IllegalArgumentException if the vertex is not contained
- */
- public abstract void remove(V vertex) throws NullPointerException, IllegalArgumentException;
-
- /**
- * Remove all the vertex contained in the graph.
- * After this method's call the graph will be empty; no vertices nor edges.
- */
- public void removeAll() {
- unMarkAll();
- for (V vertex : vertices())
- remove(vertex);
- }
-
- /**
- * Check if the edge between the two vertex passed is contained in the graph or not.
- * If one of the two vertices is not contained in the graph, then even the edge isn't
- *
- * @param vertex1 a vertex of the graph
- * @param vertex2 a vertex of the graph
- * @return true if the edge is contained, false otherwise
- * @throws NullPointerException if one of the parameters is null
- */
- public boolean containsEdge(V vertex1, V vertex2) throws NullPointerException {
- try {
- return getWeight(vertex1, vertex2) != NO_EDGE;
- } catch (IllegalArgumentException ignore) {
- return false;
- }
- }
-
- /**
- * Get the weight of the selected edge.
- * If the edge doesn't exist, then 0 is returned
- *
- * @param vertex1 a vertex of the graph
- * @param vertex2 a vertex of the graph
- * @return the weight previously set, or 0 if the edge doesn't exist
- * @throws NullPointerException if one of the parameters is null
- * @throws IllegalArgumentException if one of the vertex is not contained in the graph
- */
- public abstract int getWeight(V vertex1, V vertex2) throws NullPointerException, IllegalArgumentException;
-
- /**
- * Add an edge between the two vertex.
- * This method will overwrite any existing edge between the two vertex.
- * If there was a previous edge then it is returned
- *
- * @param edge the edge to add
- * @return 0 or the previous weight of the edge if there was already one
- * @throws NullPointerException if one of the parameter is null
- * @throws IllegalArgumentException if one of the vertex is not contained in the graph
- */
- public final int addEdge(Edge edge) throws NullPointerException, IllegalArgumentException {
- return addEdge(edge.getSource(), edge.getDestination(), edge.getWeight());
- }
-
- /**
- * Add an edge between the two vertex.
- * This method will overwrite any existing edge between the two vertices.
- * By default using this method will set the edge to the value 1.
- *
- * @param vertex1 a vertex of the graph
- * @param vertex2 a vertex of the graph
- * @throws NullPointerException if one of the parameter is null
- * @throws IllegalArgumentException if one of the vertex is not contained in the graph
- */
- public final void addEdge(V vertex1, V vertex2) throws NullPointerException, IllegalArgumentException {
- addEdge(vertex1, vertex2, 1);
- }
-
- /**
- * Add an edge between the two vertex.
- * This method will overwrite any existing edge between the two vertex.
- * If there was a previous edge then it's value is returned.
- * If the weight passed is equals to 0 or {@link Graph#NO_EDGE}, then
- * the edge will be removed.
- *
- * @param vertex1 a vertex of the graph
- * @param vertex2 a vertex of the graph
- * @param weight the weight of the edge
- * @return 0 or the previous weight of the edge if there was already one
- * @throws NullPointerException if one of the parameter is null
- * @throws IllegalArgumentException if one of the vertex is not contained in the graph
- */
- public abstract int addEdge(V vertex1, V vertex2, int weight) throws NullPointerException, IllegalArgumentException;
-
- /**
- * This particular function add an edge to the graph.
- * If one of the two, or both vertices of the edge aren't contained in the graph, then the vertices will be added.
- * This method will overwrite any existing edge between the two vertices.
- * If there was a previous edge then it is returned
- *
- * @param edge the edge to add
- * @return 0 or the previous weight of the edge if there was already one
- * @throws NullPointerException if one of the parameter is null
- */
- public final int addEdgeAndVertices(Edge edge) throws NullPointerException, IllegalArgumentException {
- return addEdgeAndVertices(edge.getSource(), edge.getDestination(), edge.getWeight());
- }
-
- /**
- * This particular function add an edge to the graph.
- * If one of the two, or both vertices aren't contained in the graph, then the vertices will be added.
- * This method will overwrite any existing edge between the two vertices.
- * By default using this method will set the edge to the value 1.
- *
- * @param vertex1 a vertex of the graph
- * @param vertex2 a vertex of the graph
- * @throws NullPointerException if one of the parameter is null
- */
- public final int addEdgeAndVertices(V vertex1, V vertex2) throws NullPointerException {
- return addEdgeAndVertices(vertex1, vertex2, 1);
- }
-
- /**
- * This particular function add an edge to the graph.
- * If one of the two, or both vertices aren't contained in the graph, then the vertices will be added.
- * This method will overwrite any existing edge between the two vertices.
- * If there was a previous edge then it is returned
- *
- * @param vertex1 a vertex of the graph
- * @param vertex2 a vertex of the graph
- * @param weight the weight of the edge
- * @return 0 or the previous weight of the edge if there was already one
- * @throws NullPointerException if one of the parameter is null
- */
- public final int addEdgeAndVertices(V vertex1, V vertex2, int weight) throws NullPointerException {
- addIfAbsent(vertex1);
- addIfAbsent(vertex2);
- return addEdge(vertex1, vertex2, weight);
- }
-
- /**
- * Add all the edges of the collection to the graph.
- * If one of the two, or both vertices aren't contained in the graph, then the vertices will be added.
- * Any null edges will be ignored.
- * This method will overwrite any existing edge between the two vertices.
- *
- * @param edges the edges to add
- * @throws NullPointerException if the set is null
- */
- public void addAllEdges(Collection> edges) throws NullPointerException {
- edges.forEach(edge -> addEdgeAndVertices(edge.getSource(), edge.getDestination(), edge.getWeight()));
- }
-
- /**
- * Remove the edge between the two vertex by setting it's value to 0.
- * If the edge doesn't exist, then this call does nothing.
- * This method is equivalent to calling {@link Graph#addEdge(Object, Object, int)} )}
- * with the weight set to {@link Graph#NO_EDGE}
- *
- * @param vertex1 a vertex of the graph
- * @param vertex2 a vertex of the graph
- * @throws NullPointerException if one of the parameters is null
- * @throws IllegalArgumentException if one of the vertex is not contained in the graph
- */
- public void removeEdge(V vertex1, V vertex2) throws NullPointerException, IllegalArgumentException {
- addEdge(vertex1, vertex2, NO_EDGE);
- }
-
- /**
- * Remove all edges form a particular vertex of the graph.
- * After this method's call the selected vertex will have 0 edges.
- * It will be no longer possible to reach this vertex from any other vertex, and vice versa.
- *
- * @param vertex a vertex of the graph
- * @throws NullPointerException if the vertex is null
- * @throws IllegalArgumentException if one of the vertex is not contained in the graph
- */
- public void removeAllEdge(V vertex) throws NullPointerException, IllegalArgumentException {
- unMark(vertex);
- remove(vertex);
- add(vertex);
- }
-
- /**
- * Remove all the edges of the graph.
- * After this method's call the graph will have only vertices, and no edge.
- */
- public void removeAllEdge() {
- Collection vertices = vertices();
- removeAll();
- addAll(vertices);
- }
-
- /**
- * Retrieve all the edges of a particular vertex.
- *
- * @param vertex a vertex of the graph
- * @return a collection of edges
- * @throws NullPointerException if the vertex is null
- * @throws IllegalArgumentException if the vertex is not contained in the graph
- */
- public abstract Collection> edgesOf(V vertex) throws NullPointerException, IllegalArgumentException;
-
- /**
- * Get all the vertices that are children of the vertex passed as parameter.
- * The vertices V(0-N) that are 'children' of a vertex V1, are all the vertices that have an edge
- * where V1 is the source of that edge.
- *
- * @param vertex the source vertex
- * @return an array of vertices
- * @throws NullPointerException if the vertex is null
- * @throws IllegalArgumentException if the vertex is not contained in the graph
- */
- public abstract Collection getChildren(V vertex) throws NullPointerException, IllegalArgumentException;
-
- /**
- * Get all the vertices that have the vertex passed as their child.
- * Basically is the opposite of {@link #getChildren(Object)}
- *
- * @param vertex a vertex of the graph
- * @return an array of ancestors of the vertex
- * @throws NullPointerException if one of the parameters is null
- * @throws IllegalArgumentException if one of the vertex is not contained in the graph
- */
- public abstract Collection getAncestors(V vertex) throws NullPointerException, IllegalArgumentException;
-
- /**
- * Get all the marks of this graph.
- * Specifically it will return a collection of marks where every mark
- * as associated at least one vertex of the graph.
- * If the graph doesn't have vertex marked then it is returned an empty collection.
- *
- * @return a collection of marks
- */
- public final Collection marks() {
- Collection ret = new HashSet<>();
- markers.forEach((v, set) -> ret.addAll(set));
- return ret;
- }
-
- /**
- * Add to the specified vertex the mark passed.
- * A vertex can have multiple marker.
- * The null marker cannot be used.
- *
- * @param vertex the vertex to mark
- * @param mark the mark to add
- * @throws NullPointerException if one of the param is null
- * @throws IllegalArgumentException if the vertex is not contained in the graph
- */
- public final void mark(V vertex, Object mark) throws NullPointerException, IllegalArgumentException {
- check(mark);
- checkVert(vertex);
- Set marks = markers.computeIfAbsent(vertex, v -> new HashSet<>());
- marks.add(mark);
- }
-
- /**
- * Remove the selected mark from the vertex.
- *
- * @param vertex the vertex where remove the mark
- * @param mark the mark to remove
- * @throws NullPointerException if a param is null
- * @throws IllegalArgumentException if the vertex is not contained in the graph
- */
- public final void unMark(V vertex, Object mark) throws NullPointerException, IllegalArgumentException {
- check(mark);
- checkVert(vertex);
- markers.computeIfPresent(vertex, (v, set) -> {
- set.remove(mark);
- if (set.size() > 0)
- return set;
- return null;
- });
- }
-
- /**
- * Unmark the vertex selected.
- * After this call the vertex will not have any marked object to himself.
- *
- * @param vertex the vertex
- * @throws NullPointerException if the vertex is null
- * @throws IllegalArgumentException if the vertex is not contained in the graph
- */
- public final void unMark(V vertex) throws NullPointerException, IllegalArgumentException {
- checkVert(vertex);
- try {
- markers.remove(vertex).clear();
- } catch (Exception ignore) {
- }
- }
-
- /**
- * Get all the vertices that are marked with the specific mark passed.
- * If there aren't vertices with that mark then it is returned an empty set.
- *
- * @param mark the mark
- * @return all the vertices that are marked with that specific mark
- * @throws NullPointerException if the mark is null
- */
- public final Collection getMarkedWith(Object mark) throws NullPointerException {
- check(mark);
- Collection vertices = new ArrayList<>(markers.size());
- markers.forEach((v, set) -> {
- if (set.contains(mark))
- vertices.add(v);
- });
- return vertices;
- }
-
- /**
- * Get all the marker of this vertex.
- * If the vertex doesn't have any mark, then it will return an empty set.
- * Note: modifying the returned collection affect the marker of the vertex.
- *
- * @param vertex the vertex
- * @return all the mark to the vertex or an empty collection if none
- * @throws NullPointerException if the vertex is null
- * @throws IllegalArgumentException if the vertex is not contained in the graph
- */
- public final Collection getMarks(V vertex) throws NullPointerException, IllegalArgumentException {
- checkVert(vertex);
- return markers.getOrDefault(vertex, new HashSet<>());
- }
-
- /**
- * Remove the selected mark from all the vertices
- *
- * @param mark the mark to remove
- * @throws NullPointerException if the mark is null
- */
- public final void unMarkAll(Object mark) throws NullPointerException {
- check(mark);
- Collection toRemove = new ArrayList<>(markers.size());
- markers.forEach((v, set) -> {
- set.remove(mark);
- if (set.size() == 0)
- toRemove.add(v);
- });
- markers.keySet().removeAll(toRemove);
- }
-
- /**
- * Remove all the marker to all the vertex.
- * After this call the {@link #getMarks(Object)} applied to any vertex will return an empty set
- */
- public final void unMarkAll() {
- markers.values().forEach(Set::clear);
- markers.clear();
- }
-
- /**
- * Get all the vertices in the graph.
- * If the graph doesn't contains vertices, it'll return an empty collection.
- *
- * @return an array that include all the vertices
- */
- public Collection vertices() {
- Collection collection = new ArrayList<>();
- forEach(collection::add);
- return collection;
- }
-
- /**
- * Get all the edges in the graph.
- * If the graph doesn't contains edges, it'll return an empty collection.
- *
- * @return a collection that include all the edges
- */
- public abstract Collection> edges();
-
- /**
- * Tells the degree of a vertex.
- * The degree of a vertex is the quantity of edges that have.
- * Basically, it'll count how many edge it have.
- *
- * @param vertex a vertex of the graph
- * @return the degree of the vertex
- * @throws NullPointerException if the vertex is null
- * @throws IllegalArgumentException if the vertex is not contained in the graph
- */
- public abstract int degree(V vertex) throws NullPointerException, IllegalArgumentException;
-
- /**
- * Tells how many vertices are in the graph.
- *
- * @return the number of vertices
- */
- public abstract int size();
-
- /**
- * Tells how many edges are in the graph.
- *
- * @return the number of edges
- */
- public abstract int numberOfEdges();
-
- /**
- * Visit the graph accordingly to the strategy that is passed.
- * Some strategy can accept a source vertex null, because they visit all the graph anyway.
- *
- * @param source the starting vertex for the visit
- * @param strategy the algorithm for visiting the graph
- * @param visit the function to apply at each vertex visited
- * @return an info of the visit if provided by the strategy
- * @throws NullPointerException if one of the parameter is null (except the consumer)
- * @throws UnsupportedOperationException in the case the visit cannot be applied to the graph
- */
- public final VisitInfo visit(V source, VisitStrategy strategy, Consumer visit) throws NullPointerException, UnsupportedOperationException {
- return strategy.visit(this, source, visit);
- }
-
- /**
- * Get a sub-graph of the current one based on the maximum depth that is given.
- * If the depth is 1 then only the source and it's children will be in the sub-graph.
- * If the depth is 2 then only the source, it's children and it's children of it's children will be in the sub-graph.
- * And so on.
- * Of course the sub-graph will contain the edges that link the vertices, but only the one selected.
- *
- * @param source the source vertex
- * @param depth the maximum depth (must be a positive number, if <=0 a graph containing only the source is returned)
- * @return a sub-graph of the original
- * @throws NullPointerException if the vertex is null
- * @throws IllegalArgumentException if the vertex is not contained
- */
- public final Graph subGraph(V source, int depth) throws NullPointerException, IllegalArgumentException {
- checkVert(source);
- Graph sub = getNewInstance();
- Set vertices = new HashSet<>(this.size() + 1, 1);
- new BFS().setMaxDepth(Math.max(depth, 0)).visit(this, source, vertices::add);
-
- sub.addAll(vertices);
- for (V src : vertices)
- for (V dest : getChildren(src))
- if (sub.contains(dest))
- sub.addEdge(new Edge<>(src, dest, this.getWeight(src, dest)));
- return sub;
- }
-
- /**
- * Get a sub-graph of the current one with only the vertex marked with the selected markers.
- * Each vertex will have all his markers and his edges, but only the ones with the destination marked with the same marker.
- * If the marker is not specified or is null then the returning graph will have all the vertices that are not marked by any marker.
- * If the graph doesn't contain any vertex with that marker then an empty graph is returned.
- *
- * @param marker one or more markers
- * @return a sub-graph of the current graph
- */
- public final Graph subGraph(Object... marker) {
- final Graph sub = getNewInstance();
- final Set allVertices = new HashSet<>();
- final Set allMarkers = new HashSet<>();
- final boolean isEmpty = (marker == null || marker.length == 0);
-
- if (!isEmpty) {
- Collections.addAll(allMarkers, marker);
- markers.forEach((v, set) -> {
- if (!Collections.disjoint(allMarkers, set))
- allVertices.add(v);
- });
- } else {
- Collection toAdd = vertices();
- toAdd.removeAll(markers.keySet());
- allVertices.addAll(toAdd);
- }
-
- sub.addAll(allVertices);
- for (V src : sub.vertices()) {
- for (Object mark : getMarks(src))
- sub.mark(src, mark);
- for (V dest : getChildren(src))
- if (sub.contains(dest))
- sub.addEdge(src, dest, getWeight(src, dest));
- }
- return sub;
- }
-
- /**
- * Get the minimum path from the source vertex to the destination vertex.
- * If the source vertex can't reach the destination, then an exception is thrown.
- *
- * @param source the vertex where to start
- * @param destination the destination chosen
- * @return an ordered list of edges from source to destination that represent the minimum path between the two vertices
- * @throws NullPointerException if one of the parameter is null (except the consumer)
- * @throws IllegalArgumentException if the vertex is not in the graph
- * @throws UnsupportedOperationException if from the source it's not possible to reach the destination
- */
- public final List> distance(V source, V destination) throws NullPointerException, IllegalArgumentException, UnsupportedOperationException {
- checkVert(source, destination);
- List> path = distance(source).get(destination);
- if (path == null)
- throw new UnsupportedOperationException(NOT_CONNECTED);
- return path;
- }
-
- /**
- * Get the minimum path from the source vertex to all the possible reachable vertices.
- *
- * @param source the vertex where to start
- * @return a map containing all the possible reachable vertices from the source and the minimum path to reach them
- * @throws NullPointerException if one of the parameter is null (except the consumer)
- * @throws IllegalArgumentException if the vertex is not in the graph
- */
- public final Map>> distance(V source) throws NullPointerException, IllegalArgumentException {
- checkVert(source);
- Dijkstra dijkstra = new Dijkstra<>();
- dijkstra.visit(this, source, null);
- return dijkstra.getLastDistance();
- }
-
-
- /**
- * Check if the object passed is not null.
- * If it's null then throws eventual exception
- *
- * @param objects the objects to test
- */
- protected final void check(Object... objects) {
- for (Object obj : objects)
- if (obj == null)
- throw new NullPointerException(PARAM_NULL);
- }
-
- /**
- * Check if the vertex passed is not null and if exist in the graph.
- * If not then throws eventual exception
- *
- * @param vertices the vertices to test
- */
- @SafeVarargs
- protected final void checkVert(V... vertices) {
- check((Object[]) vertices);
- for (V vert : vertices)
- try {
- if (!contains(vert))
- throw new IllegalArgumentException(VERTEX_NOT_CONTAINED);
- } catch (ClassCastException ignore) {
- }
- }
-}
+package berack96.lib.graph;
+
+import berack96.lib.graph.visit.VisitStrategy;
+import berack96.lib.graph.visit.impl.BFS;
+import berack96.lib.graph.visit.impl.Dijkstra;
+import berack96.lib.graph.visit.impl.VisitInfo;
+
+import java.util.*;
+import java.util.function.Consumer;
+
+/**
+ * An abstract class for the graphs.
+ * This class is used for the graphs in general.
+ * There are more specific {@link GraphDirected} and {@link GraphUndirected} edges graph interfaces.
+ *
+ * @param The Object that represent a vertex
+ * @author Berack96
+ */
+public abstract class Graph implements Iterable {
+
+ //------------------- STAIC -----------------
+
+ public static final int NO_EDGE = 0;
+ public final static String NOT_CONNECTED = "The source vertex doesn't have a path that reach the destination";
+ public final static String PARAM_NULL = "The parameter must not be null";
+ public final static String VERTEX_NOT_CONTAINED = "The vertex must be contained in the graph";
+
+ /**
+ * Create the default map. All operations are O(log(n))
+ * It returns a TreeMap with a ObjectComparator as comparator.
+ * This way all the graphs will use the same maps.
+ * It is not required to use this method, but it is highly recommended.
+ *
+ * @return A newly created TreeMap instance with ObjectsComparator as comparator
+ */
+ public final static Map getDefaultMap() {
+ return new TreeMap(ObjectsComparator.instance);
+ }
+
+ /**
+ * Create the default set. All operations are O(log(n))
+ * It returns a TreeSet with a ObjectComparator as comparator.
+ * This way all the graphs will use the same sets.
+ * It is not required to use this method, but it is highly recommended.
+ *
+ * @return A newly created TreeSet instance with ObjectsComparator as comparator
+ */
+ public final static Set getDefaultSet() {
+ return new TreeSet(ObjectsComparator.instance);
+ }
+
+ //------------------- INSTANCE -----------------
+
+ /**
+ * Map that contains the vertex as key and a set of all the marker associated with it.
+ */
+ private final Map> markers = getDefaultMap();
+
+ /**
+ * Get a new instance of this graph.
+ *
+ * @return A new instance of the graph
+ */
+ protected abstract Graph getNewInstance();
+
+ /**
+ * Check if the vertex passed is contained in the graph or not.
+ * The vertex V1 is contained in the graph G, if and only if:
+ * exist V2 in G such that V2 == V1
+ *
+ * @param vertex the vertex to check
+ * @return true if the vertex is contained, false otherwise
+ */
+ public abstract boolean contains(V vertex) throws NullPointerException;
+
+ /**
+ * Get an instance of the vertex linked with this graph.
+ * For more info see {@link Vertex}
+ *
+ * @param vertex the vertex
+ * @return a vertex
+ * @throws IllegalArgumentException if the vertex is not contained in the graph
+ */
+ public final Vertex get(V vertex) throws IllegalArgumentException {
+ checkVert(vertex);
+ return new Vertex<>(this, vertex);
+ }
+
+ /**
+ * Add the vertex to the graph. If it's already in the graph it will be replaced and all its edges will be reset.
+ * Of course the vertex added will have no marks nor edge to any other vertex nor form any other vertex.
+ *
+ * @param vertex the vertex to add
+ * @throws NullPointerException if the vertex is null
+ */
+ public abstract void add(V vertex) throws NullPointerException;
+
+ /**
+ * Add the specified vertex to the graph only if the graph doesn't contains it.
+ * The graph contains a vertex only if the method {@link #contains(Object)} returns true.
+ *
+ * @param vertex the vertex to add
+ * @return true if it adds a vertex, false if it was already in the graph
+ * @throws NullPointerException if the vertex is null
+ */
+ public final boolean addIfAbsent(V vertex) throws NullPointerException {
+ if (contains(vertex))
+ return false;
+ add(vertex);
+ return true;
+ }
+
+ /**
+ * Add all the vertices contained in the collection to the graph.
+ * If a vertex is contained in the collection and in the graph is ignored and it will not be replaced.
+ * Null vertices will be ignored and they will not be added to the graph.
+ *
+ * @param vertices a collection of the vertices to add
+ * @throws NullPointerException if the set is null
+ */
+ public void addAll(Collection vertices) throws NullPointerException {
+ check(vertices);
+ for (V vertex : vertices)
+ addIfAbsent(vertex);
+ }
+
+ /**
+ * Remove the selected vertex from the graph.
+ * After this method's call the vertex will be no longer present in the graph, and nether all his edges and marks.
+ *
+ * @param vertex the vertex to remove
+ * @throws NullPointerException if the vertex is null
+ * @throws IllegalArgumentException if the vertex is not contained
+ */
+ public abstract void remove(V vertex) throws NullPointerException, IllegalArgumentException;
+
+ /**
+ * Remove all the vertex contained in the graph.
+ * After this method's call the graph will be empty; no vertices nor edges.
+ */
+ public void removeAll() {
+ unMarkAll();
+ for (V vertex : vertices())
+ remove(vertex);
+ }
+
+ /**
+ * Check if the edge between the two vertex passed is contained in the graph or not.
+ * If one of the two vertices is not contained in the graph, then even the edge isn't
+ *
+ * @param vertex1 a vertex of the graph
+ * @param vertex2 a vertex of the graph
+ * @return true if the edge is contained, false otherwise
+ * @throws NullPointerException if one of the parameters is null
+ */
+ public boolean containsEdge(V vertex1, V vertex2) throws NullPointerException {
+ try {
+ return getWeight(vertex1, vertex2) != NO_EDGE;
+ } catch (IllegalArgumentException ignore) {
+ return false;
+ }
+ }
+
+ /**
+ * Get the weight of the selected edge.
+ * If the edge doesn't exist, then 0 is returned
+ *
+ * @param vertex1 a vertex of the graph
+ * @param vertex2 a vertex of the graph
+ * @return the weight previously set, or 0 if the edge doesn't exist
+ * @throws NullPointerException if one of the parameters is null
+ * @throws IllegalArgumentException if one of the vertex is not contained in the graph
+ */
+ public abstract int getWeight(V vertex1, V vertex2) throws NullPointerException, IllegalArgumentException;
+
+ /**
+ * Add an edge between the two vertex.
+ * This method will overwrite any existing edge between the two vertex.
+ * If there was a previous edge then it is returned
+ *
+ * @param edge the edge to add
+ * @return 0 or the previous weight of the edge if there was already one
+ * @throws NullPointerException if one of the parameter is null
+ * @throws IllegalArgumentException if one of the vertex is not contained in the graph
+ */
+ public final int addEdge(Edge edge) throws NullPointerException, IllegalArgumentException {
+ return addEdge(edge.getSource(), edge.getDestination(), edge.getWeight());
+ }
+
+ /**
+ * Add an edge between the two vertex.
+ * This method will overwrite any existing edge between the two vertices.
+ * By default using this method will set the edge to the value 1.
+ *
+ * @param vertex1 a vertex of the graph
+ * @param vertex2 a vertex of the graph
+ * @throws NullPointerException if one of the parameter is null
+ * @throws IllegalArgumentException if one of the vertex is not contained in the graph
+ */
+ public final void addEdge(V vertex1, V vertex2) throws NullPointerException, IllegalArgumentException {
+ addEdge(vertex1, vertex2, 1);
+ }
+
+ /**
+ * Add an edge between the two vertex.
+ * This method will overwrite any existing edge between the two vertex.
+ * If there was a previous edge then it's value is returned.
+ * If the weight passed is equals to 0 or {@link Graph#NO_EDGE}, then
+ * the edge will be removed.
+ *
+ * @param vertex1 a vertex of the graph
+ * @param vertex2 a vertex of the graph
+ * @param weight the weight of the edge
+ * @return 0 or the previous weight of the edge if there was already one
+ * @throws NullPointerException if one of the parameter is null
+ * @throws IllegalArgumentException if one of the vertex is not contained in the graph
+ */
+ public abstract int addEdge(V vertex1, V vertex2, int weight) throws NullPointerException, IllegalArgumentException;
+
+ /**
+ * This particular function add an edge to the graph.
+ * If one of the two, or both vertices of the edge aren't contained in the graph, then the vertices will be added.
+ * This method will overwrite any existing edge between the two vertices.
+ * If there was a previous edge then it is returned
+ *
+ * @param edge the edge to add
+ * @return 0 or the previous weight of the edge if there was already one
+ * @throws NullPointerException if one of the parameter is null
+ */
+ public final int addEdgeAndVertices(Edge edge) throws NullPointerException, IllegalArgumentException {
+ return addEdgeAndVertices(edge.getSource(), edge.getDestination(), edge.getWeight());
+ }
+
+ /**
+ * This particular function add an edge to the graph.
+ * If one of the two, or both vertices aren't contained in the graph, then the vertices will be added.
+ * This method will overwrite any existing edge between the two vertices.
+ * By default using this method will set the edge to the value 1.
+ *
+ * @param vertex1 a vertex of the graph
+ * @param vertex2 a vertex of the graph
+ * @throws NullPointerException if one of the parameter is null
+ */
+ public final int addEdgeAndVertices(V vertex1, V vertex2) throws NullPointerException {
+ return addEdgeAndVertices(vertex1, vertex2, 1);
+ }
+
+ /**
+ * This particular function add an edge to the graph.
+ * If one of the two, or both vertices aren't contained in the graph, then the vertices will be added.
+ * This method will overwrite any existing edge between the two vertices.
+ * If there was a previous edge then it is returned
+ *
+ * @param vertex1 a vertex of the graph
+ * @param vertex2 a vertex of the graph
+ * @param weight the weight of the edge
+ * @return 0 or the previous weight of the edge if there was already one
+ * @throws NullPointerException if one of the parameter is null
+ */
+ public final int addEdgeAndVertices(V vertex1, V vertex2, int weight) throws NullPointerException {
+ addIfAbsent(vertex1);
+ addIfAbsent(vertex2);
+ return addEdge(vertex1, vertex2, weight);
+ }
+
+ /**
+ * Add all the edges of the collection to the graph.
+ * If one of the two, or both vertices aren't contained in the graph, then the vertices will be added.
+ * Any null edges will be ignored.
+ * This method will overwrite any existing edge between the two vertices.
+ *
+ * @param edges the edges to add
+ * @throws NullPointerException if the set is null
+ */
+ public void addAllEdges(Collection> edges) throws NullPointerException {
+ edges.forEach(edge -> addEdgeAndVertices(edge.getSource(), edge.getDestination(), edge.getWeight()));
+ }
+
+ /**
+ * Remove the edge between the two vertex by setting it's value to 0.
+ * If the edge doesn't exist, then this call does nothing.
+ * This method is equivalent to calling {@link Graph#addEdge(Object, Object, int)} )}
+ * with the weight set to {@link Graph#NO_EDGE}
+ *
+ * @param vertex1 a vertex of the graph
+ * @param vertex2 a vertex of the graph
+ * @throws NullPointerException if one of the parameters is null
+ * @throws IllegalArgumentException if one of the vertex is not contained in the graph
+ */
+ public void removeEdge(V vertex1, V vertex2) throws NullPointerException, IllegalArgumentException {
+ addEdge(vertex1, vertex2, NO_EDGE);
+ }
+
+ /**
+ * Remove all edges form a particular vertex of the graph.
+ * After this method's call the selected vertex will have 0 edges.
+ * It will be no longer possible to reach this vertex from any other vertex, and vice versa.
+ *
+ * @param vertex a vertex of the graph
+ * @throws NullPointerException if the vertex is null
+ * @throws IllegalArgumentException if one of the vertex is not contained in the graph
+ */
+ public void removeAllEdge(V vertex) throws NullPointerException, IllegalArgumentException {
+ unMark(vertex);
+ remove(vertex);
+ add(vertex);
+ }
+
+ /**
+ * Remove all the edges of the graph.
+ * After this method's call the graph will have only vertices, and no edge.
+ */
+ public void removeAllEdge() {
+ Set vertices = vertices();
+ removeAll();
+ addAll(vertices);
+ }
+
+ /**
+ * Retrieve all the edges of a particular vertex.
+ *
+ * @param vertex a vertex of the graph
+ * @return a set of edges
+ * @throws NullPointerException if the vertex is null
+ * @throws IllegalArgumentException if the vertex is not contained in the graph
+ */
+ public abstract Set> edgesOf(V vertex) throws NullPointerException, IllegalArgumentException;
+
+ /**
+ * Get all the vertices that are children of the vertex passed as parameter.
+ * The vertices V(0-N) that are 'children' of a vertex V1, are all the vertices that have an edge
+ * where V1 is the source of that edge.
+ *
+ * @param vertex the source vertex
+ * @return a set of vertices
+ * @throws NullPointerException if the vertex is null
+ * @throws IllegalArgumentException if the vertex is not contained in the graph
+ */
+ public abstract Set getChildren(V vertex) throws NullPointerException, IllegalArgumentException;
+
+ /**
+ * Get all the vertices that have the vertex passed as their child.
+ * Basically is the opposite of {@link #getChildren(Object)}
+ *
+ * @param vertex a vertex of the graph
+ * @return a set of ancestors of the vertex
+ * @throws NullPointerException if one of the parameters is null
+ * @throws IllegalArgumentException if one of the vertex is not contained in the graph
+ */
+ public abstract Set getAncestors(V vertex) throws NullPointerException, IllegalArgumentException;
+
+ /**
+ * Get all the marks of this graph.
+ * Specifically it will return a Set of marks where every mark
+ * as associated at least one vertex of the graph.
+ * If the graph doesn't have vertex marked then it is returned an empty Set.
+ *
+ * @return a set of marks
+ */
+ public final Set marks() {
+ Set ret = getDefaultSet();
+ markers.forEach((v, set) -> ret.addAll(set));
+ return ret;
+ }
+
+ /**
+ * Add to the specified vertex the mark passed.
+ * A vertex can have multiple marker.
+ * The null marker cannot be used.
+ *
+ * @param vertex the vertex to mark
+ * @param mark the mark to add
+ * @throws NullPointerException if one of the param is null
+ * @throws IllegalArgumentException if the vertex is not contained in the graph
+ */
+ public final void mark(V vertex, Object mark) throws NullPointerException, IllegalArgumentException {
+ check(mark);
+ checkVert(vertex);
+ Set marks = markers.computeIfAbsent(vertex, v -> getDefaultSet());
+ marks.add(mark);
+ }
+
+ /**
+ * Remove the selected mark from the vertex.
+ *
+ * @param vertex the vertex where remove the mark
+ * @param mark the mark to remove
+ * @throws NullPointerException if a param is null
+ * @throws IllegalArgumentException if the vertex is not contained in the graph
+ */
+ public final void unMark(V vertex, Object mark) throws NullPointerException, IllegalArgumentException {
+ check(mark);
+ checkVert(vertex);
+ markers.computeIfPresent(vertex, (v, set) -> {
+ set.remove(mark);
+ if (set.size() > 0)
+ return set;
+ return null;
+ });
+ }
+
+ /**
+ * Unmark the vertex selected.
+ * After this call the vertex will not have any marked object to himself.
+ *
+ * @param vertex the vertex
+ * @throws NullPointerException if the vertex is null
+ * @throws IllegalArgumentException if the vertex is not contained in the graph
+ */
+ public final void unMark(V vertex) throws NullPointerException, IllegalArgumentException {
+ checkVert(vertex);
+ try {
+ markers.remove(vertex).clear();
+ } catch (Exception ignore) {
+ }
+ }
+
+ /**
+ * Get all the vertices that are marked with the specific mark passed.
+ * If there aren't vertices with that mark then it is returned an empty set.
+ *
+ * @param mark the mark
+ * @return a set of all the vertices that are marked with that specific mark
+ * @throws NullPointerException if the mark is null
+ */
+ public final Set getMarkedWith(Object mark) throws NullPointerException {
+ check(mark);
+ Set vertices = getDefaultSet();
+ markers.forEach((v, set) -> {
+ if (set.contains(mark))
+ vertices.add(v);
+ });
+ return vertices;
+ }
+
+ /**
+ * Get all the marker of this vertex.
+ * If the vertex doesn't have any mark, then it will return an empty set.
+ * Note: modifying the returned Set affect the marker of the vertex.
+ *
+ * @param vertex the vertex
+ * @return a set of all the mark to the vertex or an empty Set if none
+ * @throws NullPointerException if the vertex is null
+ * @throws IllegalArgumentException if the vertex is not contained in the graph
+ */
+ public final Set getMarks(V vertex) throws NullPointerException, IllegalArgumentException {
+ checkVert(vertex);
+ return markers.getOrDefault(vertex, getDefaultSet());
+ }
+
+ /**
+ * Remove the selected mark from all the vertices
+ *
+ * @param mark the mark to remove
+ * @throws NullPointerException if the mark is null
+ */
+ public final void unMarkAll(Object mark) throws NullPointerException {
+ check(mark);
+ Set toRemove = getDefaultSet();
+ markers.forEach((v, set) -> {
+ set.remove(mark);
+ if (set.size() == 0)
+ toRemove.add(v);
+ });
+ markers.keySet().removeAll(toRemove);
+ }
+
+ /**
+ * Remove all the marker to all the vertex.
+ * After this call the {@link #getMarks(Object)} applied to any vertex will return an empty set
+ */
+ public final void unMarkAll() {
+ markers.values().forEach(Set::clear);
+ markers.clear();
+ }
+
+ /**
+ * Get all the vertices in the graph.
+ * If the graph doesn't contains vertices, it'll return an empty Set.
+ *
+ * @return a set that include all the vertices
+ */
+ public Set vertices() {
+ Set vertices = getDefaultSet();
+ forEach(vertices::add);
+ return vertices;
+ }
+
+ /**
+ * Get all the edges in the graph.
+ * If the graph doesn't contains edges, it'll return an empty Set.
+ *
+ * @return a Set that include all the edges
+ */
+ public abstract Set> edges();
+
+ /**
+ * Tells the degree of a vertex.
+ * The degree of a vertex is the quantity of edges that have.
+ * Basically, it'll count how many edge it have.
+ *
+ * @param vertex a vertex of the graph
+ * @return the degree of the vertex
+ * @throws NullPointerException if the vertex is null
+ * @throws IllegalArgumentException if the vertex is not contained in the graph
+ */
+ public abstract int degree(V vertex) throws NullPointerException, IllegalArgumentException;
+
+ /**
+ * Tells how many vertices are in the graph.
+ *
+ * @return the number of vertices
+ */
+ public abstract int size();
+
+ /**
+ * Tells how many edges are in the graph.
+ *
+ * @return the number of edges
+ */
+ public abstract int numberOfEdges();
+
+ /**
+ * Visit the graph accordingly to the strategy that is passed.
+ * Some strategy can accept a source vertex null, because they visit all the graph anyway.
+ *
+ * @param source the starting vertex for the visit
+ * @param strategy the algorithm for visiting the graph
+ * @param visit the function to apply at each vertex visited
+ * @return an info of the visit if provided by the strategy
+ * @throws NullPointerException if one of the parameter is null (except the consumer)
+ * @throws UnsupportedOperationException in the case the visit cannot be applied to the graph
+ */
+ public final VisitInfo visit(V source, VisitStrategy strategy, Consumer visit) throws NullPointerException, UnsupportedOperationException {
+ return strategy.visit(this, source, visit);
+ }
+
+ /**
+ * Get a sub-graph of the current one based on the maximum depth that is given.
+ * If the depth is 1 then only the source and it's children will be in the sub-graph.
+ * If the depth is 2 then only the source, it's children and it's children of it's children will be in the sub-graph.
+ * And so on.
+ * Of course the sub-graph will contain the edges that link the vertices, but only the one selected.
+ *
+ * @param source the source vertex
+ * @param depth the maximum depth (must be a positive number, if <=0 a graph containing only the source is returned)
+ * @return a sub-graph of the original
+ * @throws NullPointerException if the vertex is null
+ * @throws IllegalArgumentException if the vertex is not contained
+ */
+ public final Graph subGraph(V source, int depth) throws NullPointerException, IllegalArgumentException {
+ checkVert(source);
+ Graph sub = getNewInstance();
+ Set vertices = getDefaultSet();
+ new BFS().setMaxDepth(Math.max(depth, 0)).visit(this, source, vertices::add);
+
+ sub.addAll(vertices);
+ for (V src : vertices)
+ for (V dest : getChildren(src))
+ if (sub.contains(dest))
+ sub.addEdge(src, dest, this.getWeight(src, dest));
+ return sub;
+ }
+
+ /**
+ * Get a sub-graph of the current one with only the vertex marked with the selected markers. (OR set operation)
+ * Each vertex will have all his markers and his edges, but only the ones with the destination marked with the same marker.
+ * If the marker is not specified or is null then the returning graph will have all the vertices that are not marked by any marker.
+ * If in the list of markers there is a null marker it will be skipped.
+ * If the graph doesn't contain any vertex with any marker passed then an empty graph is returned.
+ *
+ * @param marker one or more markers
+ * @return a sub-graph of the current graph
+ */
+ public final Graph subGraph(Object... marker) {
+ final Graph sub = getNewInstance();
+ final Set allVertices = getDefaultSet();
+ final Set allMarkers = getDefaultSet();
+
+ if (marker != null && marker.length > 0)
+ for(int i=0; i 0)
+ markers.forEach((v, set) -> {
+ if (!Collections.disjoint(allMarkers, set))
+ allVertices.add(v);
+ });
+ else {
+ Set toAdd = vertices();
+ toAdd.removeAll(markers.keySet());
+ allVertices.addAll(toAdd);
+ }
+
+ sub.addAll(allVertices);
+ for (V src : sub.vertices()) {
+ for (Object mark : getMarks(src))
+ sub.mark(src, mark);
+ for (V dest : getChildren(src))
+ if (sub.contains(dest))
+ sub.addEdge(src, dest, getWeight(src, dest));
+ }
+ return sub;
+ }
+
+ /**
+ * Get the minimum path from the source vertex to the destination vertex.
+ * If the source vertex can't reach the destination, then an exception is thrown.
+ *
+ * @param source the vertex where to start
+ * @param destination the destination chosen
+ * @return an ordered list of edges from source to destination that represent the minimum path between the two vertices
+ * @throws NullPointerException if one of the parameter is null (except the consumer)
+ * @throws IllegalArgumentException if the vertex is not in the graph
+ * @throws UnsupportedOperationException if from the source it's not possible to reach the destination
+ */
+ public final List> distance(V source, V destination) throws NullPointerException, IllegalArgumentException, UnsupportedOperationException {
+ checkVert(source, destination);
+ List> path = distance(source).get(destination);
+ if (path == null)
+ throw new UnsupportedOperationException(NOT_CONNECTED);
+ return path;
+ }
+
+ /**
+ * Get the minimum path from the source vertex to all the possible reachable vertices.
+ *
+ * @param source the vertex where to start
+ * @return a map containing all the possible reachable vertices from the source and the minimum path to reach them
+ * @throws NullPointerException if one of the parameter is null (except the consumer)
+ * @throws IllegalArgumentException if the vertex is not in the graph
+ */
+ public final Map>> distance(V source) throws NullPointerException, IllegalArgumentException {
+ checkVert(source);
+ Dijkstra dijkstra = new Dijkstra<>();
+ dijkstra.visit(this, source, null);
+ return dijkstra.getLastDistance();
+ }
+
+ /**
+ * Check if the object passed is not null.
+ * If it's null then throws eventual exception
+ *
+ * @param objects the objects to test
+ */
+ protected final void check(Object... objects) {
+ for (Object obj : objects)
+ if (obj == null)
+ throw new NullPointerException(PARAM_NULL);
+ }
+
+ /**
+ * Check if the vertex passed is not null and if exist in the graph.
+ * If not then throws eventual exception
+ *
+ * @param vertices the vertices to test
+ */
+ @SafeVarargs
+ protected final void checkVert(V... vertices) {
+ check((Object[]) vertices);
+ for (V vert : vertices)
+ try {
+ if (!contains(vert))
+ throw new IllegalArgumentException(VERTEX_NOT_CONTAINED);
+ } catch (ClassCastException ignore) {
+ }
+ }
+}
diff --git a/src/berack96/lib/graph/GraphDirected.java b/src/main/java/berack96/lib/graph/GraphDirected.java
similarity index 86%
rename from src/berack96/lib/graph/GraphDirected.java
rename to src/main/java/berack96/lib/graph/GraphDirected.java
index bd2abe5..9bbce28 100644
--- a/src/berack96/lib/graph/GraphDirected.java
+++ b/src/main/java/berack96/lib/graph/GraphDirected.java
@@ -4,10 +4,8 @@ import berack96.lib.graph.visit.VisitSCC;
import berack96.lib.graph.visit.VisitTopological;
import berack96.lib.graph.visit.impl.Tarjan;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
import java.util.List;
+import java.util.Set;
/**
* This is a more specific interface for an implementation of a Undirected Graph.
@@ -70,17 +68,17 @@ public abstract class GraphDirected extends Graph {
/**
* Retrieve all the edges of a particular vertex.
* Note: the edges that are returned are the one that have this vertex as destination and another as source.
- * Note2: depending on the implementation, modifying the returned collection
+ * Note2: depending on the implementation, modifying the returned Set
* could affect the graph behavior and the changes could be reflected to the graph.
*
* @param vertex a vertex of the graph
- * @return a collection of edges
+ * @return a Set of edges
* @throws NullPointerException if the vertex is null
* @throws IllegalArgumentException if the vertex is not contained in the graph
*/
- public Collection> getEdgesIn(V vertex) throws NullPointerException, IllegalArgumentException {
- Collection ancestors = getAncestors(vertex);
- Collection> edgesIn = new HashSet<>(ancestors.size());
+ public Set> getEdgesIn(V vertex) throws NullPointerException, IllegalArgumentException {
+ Set ancestors = getAncestors(vertex);
+ Set> edgesIn = getDefaultSet();
for (V ancestor : ancestors) {
int weight = getWeight(ancestor, vertex);
@@ -93,17 +91,17 @@ public abstract class GraphDirected extends Graph {
/**
* Retrieve all the edges that goes OUT of a particular vertex.
* Note: the edges that are returned are the one that have this vertex as source and another one as destination.
- * Note2: depending on the implementation, modifying the returned collection
+ * Note2: depending on the implementation, modifying the returned Set
* could affect the graph behavior and the changes could be reflected to the graph.
*
* @param vertex a vertex of the graph
- * @return a collection of edges
+ * @return a Set of edges
* @throws NullPointerException if the vertex is null
* @throws IllegalArgumentException if the vertex is not contained in the graph
*/
- public Collection> getEdgesOut(V vertex) throws NullPointerException, IllegalArgumentException {
- Collection children = getChildren(vertex);
- Collection> edgesOut = new HashSet<>(children.size());
+ public Set> getEdgesOut(V vertex) throws NullPointerException, IllegalArgumentException {
+ Set children = getChildren(vertex);
+ Set> edgesOut = getDefaultSet();
for (V child : children) {
int weight = getWeight(vertex, child);
@@ -178,26 +176,26 @@ public abstract class GraphDirected extends Graph {
* The strongly connected components or disconnected components of an arbitrary directed graph
* form a partition into subgraphs that are themselves strongly connected.
*
- * @return a collection containing the strongly connected components
+ * @return a Set containing the strongly connected components
*/
- public final Collection> stronglyConnectedComponents() {
+ public final Set> stronglyConnectedComponents() {
VisitSCC visit = new Tarjan<>();
visit.visit(this, null, null);
return visit.getSCC();
}
@Override
- public Collection> edgesOf(V vertex) throws NullPointerException, IllegalArgumentException {
- Collection> edges = getEdgesIn(vertex);
+ public Set> edgesOf(V vertex) throws NullPointerException, IllegalArgumentException {
+ Set> edges = getEdgesIn(vertex);
edges.addAll(getEdgesOut(vertex));
return edges;
}
@Override
- public Collection> edges() {
- Collection> collection = new ArrayList<>();
- forEach(v -> collection.addAll(getEdgesIn(v)));
- return collection;
+ public Set> edges() {
+ Set> set = getDefaultSet();
+ forEach(v -> set.addAll(getEdgesIn(v)));
+ return set;
}
@Override
diff --git a/src/berack96/lib/graph/GraphUndirected.java b/src/main/java/berack96/lib/graph/GraphUndirected.java
similarity index 70%
rename from src/berack96/lib/graph/GraphUndirected.java
rename to src/main/java/berack96/lib/graph/GraphUndirected.java
index e07fb47..96bcb37 100644
--- a/src/berack96/lib/graph/GraphUndirected.java
+++ b/src/main/java/berack96/lib/graph/GraphUndirected.java
@@ -3,8 +3,7 @@ package berack96.lib.graph;
import berack96.lib.graph.visit.VisitMST;
import berack96.lib.graph.visit.impl.Prim;
-import java.util.Collection;
-import java.util.LinkedList;
+import java.util.Set;
/**
* This is a more specific interface for an implementation of a Directed Graph.
@@ -19,27 +18,27 @@ public abstract class GraphUndirected extends Graph {
/**
* The connected components of an arbitrary undirected graph form a partition into subgraphs that are themselves connected.
*
- * @return a collection containing the strongly connected components
+ * @return a Set containing the strongly connected components
*/
- public Collection> connectedComponents() {
+ public Set> connectedComponents() {
return null;
}
/**
* minimum spanning forest or minimum spamming tree of the graph
*
- * @return A collection of edges representing the M.S.F.
+ * @return A Set of edges representing the M.S.F.
*/
- public Collection> minimumSpanningForest() {
+ public Set> minimumSpanningForest() {
VisitMST visit = new Prim<>();
visit.visit(this, iterator().next(), null);
return visit.getMST();
}
@Override
- public Collection> edgesOf(V vertex) throws NullPointerException, IllegalArgumentException {
+ public Set> edgesOf(V vertex) throws NullPointerException, IllegalArgumentException {
checkVert(vertex);
- Collection> edges = new LinkedList<>();
+ Set> edges = getDefaultSet();
getChildren(vertex).forEach(v -> edges.add(new Edge<>(vertex, v, getWeight(vertex, v))));
return edges;
}
diff --git a/src/main/java/berack96/lib/graph/ObjectsComparator.java b/src/main/java/berack96/lib/graph/ObjectsComparator.java
new file mode 100644
index 0000000..e3668dd
--- /dev/null
+++ b/src/main/java/berack96/lib/graph/ObjectsComparator.java
@@ -0,0 +1,18 @@
+package berack96.lib.graph;
+import java.util.Comparator;
+
+/**
+ * Compare two arbitrary objects.
+ * It uses the method hashCode that every object has to compare two objects.
+ * This is a simple use
+ */
+public class ObjectsComparator implements Comparator {
+ static public final ObjectsComparator instance = new ObjectsComparator();
+
+ private ObjectsComparator(){};
+
+ @Override
+ public int compare(Object o1, Object o2) {
+ return o1.hashCode() - o2.hashCode();
+ }
+}
diff --git a/src/berack96/lib/graph/Vertex.java b/src/main/java/berack96/lib/graph/Vertex.java
similarity index 100%
rename from src/berack96/lib/graph/Vertex.java
rename to src/main/java/berack96/lib/graph/Vertex.java
diff --git a/src/berack96/lib/graph/impl/ListGraph.java b/src/main/java/berack96/lib/graph/impl/ListGraph.java
similarity index 86%
rename from src/berack96/lib/graph/impl/ListGraph.java
rename to src/main/java/berack96/lib/graph/impl/ListGraph.java
index fb29b81..88acea1 100644
--- a/src/berack96/lib/graph/impl/ListGraph.java
+++ b/src/main/java/berack96/lib/graph/impl/ListGraph.java
@@ -1,160 +1,161 @@
-package berack96.lib.graph.impl;
-
-import berack96.lib.graph.Graph;
-import berack96.lib.graph.GraphDirected;
-
-import java.util.*;
-import java.util.concurrent.atomic.AtomicInteger;
-
-/**
- * An implementation of the graph using an adjacent list for representing the edges
- *
- * @param the vertex
- * @author Berack96
- */
-public class ListGraph extends GraphDirected {
-
- final private Map> adj = new Hashtable<>();
-
- @Override
- public Iterator iterator() {
- return adj.keySet().iterator();
- }
-
- @Override
- protected Graph getNewInstance() {
- return new ListGraph<>();
- }
-
- @Override
- public void add(V vertex) {
- check(vertex);
- if (adj.containsKey(vertex))
- removeAllEdge(vertex);
- else
- adj.put(vertex, new LinkedList<>());
- }
-
- @Override
- public boolean contains(V vertex) {
- check(vertex);
- return adj.containsKey(vertex);
- }
-
- @Override
- public void remove(V vertex) {
- checkVert(vertex);
- adj.remove(vertex);
- adj.forEach((v, list) -> list.remove(getAdj(list, vertex)));
- }
-
- @Override
- public int addEdge(V vertex1, V vertex2, int weight) {
- checkVert(vertex1, vertex2);
-
- List list = adj.get(vertex1);
- Adj a = getAdj(list, vertex2);
- int old = a == null ? NO_EDGE : a.weight;
-
- if (weight == NO_EDGE)
- list.remove(a);
- else if (old == NO_EDGE)
- list.add(new Adj(vertex2, weight));
- else
- a.weight = weight;
- return old;
- }
-
- @Override
- public int getWeight(V vertex1, V vertex2) {
- checkVert(vertex1, vertex2);
- Adj a = getAdj(adj.get(vertex1), vertex2);
- return a == null ? NO_EDGE : a.weight;
- }
-
- @Override
- public Collection getChildren(V vertex) throws NullPointerException, IllegalArgumentException {
- checkVert(vertex);
- Collection children = new HashSet<>();
- for (Adj adj : adj.get(vertex))
- children.add(adj.vertex);
- return children;
- }
-
- @Override
- public Collection getAncestors(V vertex) throws NullPointerException, IllegalArgumentException {
- checkVert(vertex);
- Collection ancestors = new HashSet<>();
- adj.forEach((v, list) -> {
- if (getAdj(list, vertex) != null)
- ancestors.add(v);
- });
-
- return ancestors;
- }
-
-
- /**
- * From here on there are some optimization for the methods of the generic DirectedGraph
- **/
-
- @Override
- public int size() {
- return adj.size();
- }
-
- @Override
- public int numberOfEdges() {
- AtomicInteger size = new AtomicInteger(0);
- adj.values().forEach(list -> size.addAndGet(list.size()));
- return size.get();
- }
-
- @Override
- public int degreeIn(V vertex) throws NullPointerException, IllegalArgumentException {
- checkVert(vertex);
- AtomicInteger degree = new AtomicInteger(0);
- adj.values().forEach(list -> degree.addAndGet(getAdj(list, vertex) != null ? 1 : 0));
- return degree.get();
- }
-
- @Override
- public int degreeOut(V vertex) throws NullPointerException, IllegalArgumentException {
- checkVert(vertex);
- return adj.get(vertex).size();
- }
-
- @Override
- public void removeAllEdge(V vertex) throws NullPointerException, IllegalArgumentException {
- checkVert(vertex);
- adj.get(vertex).clear();
- adj.forEach((v, list) -> list.remove(getAdj(list, vertex)));
- }
-
- @Override
- public void removeAllEdge() {
- adj.forEach((v, list) -> list.clear());
- }
-
- @Override
- public void removeAll() {
- adj.clear();
- }
-
- private Adj getAdj(List list, V vertex) {
- for (Adj adj : list)
- if (Objects.equals(adj.vertex, vertex))
- return adj;
- return null;
- }
-
- private class Adj {
- private final V vertex;
- private int weight;
-
- private Adj(V vertex, int weight) {
- this.vertex = vertex;
- this.weight = weight;
- }
- }
-}
+package berack96.lib.graph.impl;
+
+import berack96.lib.graph.Graph;
+import berack96.lib.graph.GraphDirected;
+
+import java.util.*;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * An implementation of the graph using an adjacent list for representing the edges
+ *
+ * @param the vertex
+ * @author Berack96
+ */
+public class ListGraph extends GraphDirected {
+
+ // in case of thread safety use -> Collections.synchronizedSortedMap(TreeMap)
+ final private Map> adj = getDefaultMap();
+
+ @Override
+ public Iterator iterator() {
+ return adj.keySet().iterator();
+ }
+
+ @Override
+ protected Graph getNewInstance() {
+ return new ListGraph<>();
+ }
+
+ @Override
+ public void add(V vertex) {
+ check(vertex);
+ if (adj.containsKey(vertex))
+ removeAllEdge(vertex);
+ else
+ adj.put(vertex, new LinkedList<>());
+ }
+
+ @Override
+ public boolean contains(V vertex) {
+ check(vertex);
+ return adj.containsKey(vertex);
+ }
+
+ @Override
+ public void remove(V vertex) {
+ checkVert(vertex);
+ adj.remove(vertex);
+ adj.forEach((v, list) -> list.remove(getAdj(list, vertex)));
+ }
+
+ @Override
+ public int addEdge(V vertex1, V vertex2, int weight) {
+ checkVert(vertex1, vertex2);
+
+ List list = adj.get(vertex1);
+ Adj a = getAdj(list, vertex2);
+ int old = a == null ? NO_EDGE : a.weight;
+
+ if (weight == NO_EDGE)
+ list.remove(a);
+ else if (old == NO_EDGE)
+ list.add(new Adj(vertex2, weight));
+ else
+ a.weight = weight;
+ return old;
+ }
+
+ @Override
+ public int getWeight(V vertex1, V vertex2) {
+ checkVert(vertex1, vertex2);
+ Adj a = getAdj(adj.get(vertex1), vertex2);
+ return a == null ? NO_EDGE : a.weight;
+ }
+
+ @Override
+ public Set getChildren(V vertex) throws NullPointerException, IllegalArgumentException {
+ checkVert(vertex);
+ Set children = getDefaultSet();
+ for (Adj adj : adj.get(vertex))
+ children.add(adj.vertex);
+ return children;
+ }
+
+ @Override
+ public Set getAncestors(V vertex) throws NullPointerException, IllegalArgumentException {
+ checkVert(vertex);
+ Set ancestors = getDefaultSet();
+ adj.forEach((v, list) -> {
+ if (getAdj(list, vertex) != null)
+ ancestors.add(v);
+ });
+
+ return ancestors;
+ }
+
+
+ /**
+ * From here on there are some optimization for the methods of the generic DirectedGraph
+ **/
+
+ @Override
+ public int size() {
+ return adj.size();
+ }
+
+ @Override
+ public int numberOfEdges() {
+ AtomicInteger size = new AtomicInteger(0);
+ adj.values().forEach(list -> size.addAndGet(list.size()));
+ return size.get();
+ }
+
+ @Override
+ public int degreeIn(V vertex) throws NullPointerException, IllegalArgumentException {
+ checkVert(vertex);
+ AtomicInteger degree = new AtomicInteger(0);
+ adj.values().forEach(list -> degree.addAndGet(getAdj(list, vertex) != null ? 1 : 0));
+ return degree.get();
+ }
+
+ @Override
+ public int degreeOut(V vertex) throws NullPointerException, IllegalArgumentException {
+ checkVert(vertex);
+ return adj.get(vertex).size();
+ }
+
+ @Override
+ public void removeAllEdge(V vertex) throws NullPointerException, IllegalArgumentException {
+ checkVert(vertex);
+ adj.get(vertex).clear();
+ adj.forEach((v, list) -> list.remove(getAdj(list, vertex)));
+ }
+
+ @Override
+ public void removeAllEdge() {
+ adj.forEach((v, list) -> list.clear());
+ }
+
+ @Override
+ public void removeAll() {
+ adj.clear();
+ }
+
+ private Adj getAdj(List list, V vertex) {
+ for (Adj adj : list)
+ if (Objects.equals(adj.vertex, vertex))
+ return adj;
+ return null;
+ }
+
+ private class Adj {
+ private final V vertex;
+ private int weight;
+
+ private Adj(V vertex, int weight) {
+ this.vertex = vertex;
+ this.weight = weight;
+ }
+ }
+}
diff --git a/src/berack96/lib/graph/impl/MapGraph.java b/src/main/java/berack96/lib/graph/impl/MapGraph.java
similarity index 79%
rename from src/berack96/lib/graph/impl/MapGraph.java
rename to src/main/java/berack96/lib/graph/impl/MapGraph.java
index a477fa2..600de5c 100644
--- a/src/berack96/lib/graph/impl/MapGraph.java
+++ b/src/main/java/berack96/lib/graph/impl/MapGraph.java
@@ -1,115 +1,116 @@
-package berack96.lib.graph.impl;
-
-import berack96.lib.graph.Graph;
-import berack96.lib.graph.GraphDirected;
-
-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
- * @author Berack96
- */
-public class MapGraph extends GraphDirected {
-
- /**
- * 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
- public void add(V vertex) {
- check(vertex);
- edges.computeIfAbsent(vertex, v -> new HashMap<>());
- edges.forEach((v, adj) -> adj.remove(vertex));
- edges.get(vertex).clear();
- }
-
- @Override
- public boolean contains(V vertex) {
- check(vertex);
- return edges.containsKey(vertex);
- }
-
- @Override
- public void remove(V vertex) {
- checkVert(vertex);
- edges.remove(vertex);
- edges.forEach((v, map) -> map.remove(vertex));
- }
-
- @Override
- public int addEdge(V vertex1, V vertex2, int weight) {
- checkVert(vertex1, vertex2);
- Map edge = edges.get(vertex1);
- Integer old = edge.get(vertex2);
- old = old == null ? NO_EDGE : old;
-
- if (weight == NO_EDGE)
- edge.remove(vertex2);
- else
- edge.put(vertex2, weight);
- return old;
- }
-
- @Override
- public int getWeight(V vertex1, V vertex2) {
- checkVert(vertex1, vertex2);
- Integer weight = edges.get(vertex1).get(vertex2);
- return weight == null ? NO_EDGE : weight;
- }
-
- @Override
- public Collection getChildren(V vertex) throws NullPointerException, IllegalArgumentException {
- checkVert(vertex);
- return new HashSet<>(edges.get(vertex).keySet());
- }
-
- @Override
- public Collection getAncestors(V vertex) throws NullPointerException, IllegalArgumentException {
- checkVert(vertex);
- Collection ancestors = new HashSet<>();
- edges.forEach((v, adj) -> {
- if (adj.containsKey(vertex))
- ancestors.add(v);
- });
- return ancestors;
- }
-
- @Override
- public void removeAll() {
- edges.clear();
- }
-
- @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();
- }
-}
+package berack96.lib.graph.impl;
+
+import berack96.lib.graph.Graph;
+import berack96.lib.graph.GraphDirected;
+
+import java.util.*;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Graph that uses TreeMap 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.
+ * "Fast" in this case means O(log(n)) since it is a tree, so not tecnically as fast as O(1),
+ * but better than O(n).
+ *
+ * @param the vertices
+ * @author Berack96
+ */
+public class MapGraph extends GraphDirected {
+
+ /**
+ * 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 = getDefaultMap();
+
+ @Override
+ public Iterator iterator() {
+ return edges.keySet().iterator();
+ }
+
+
+ @Override
+ protected Graph getNewInstance() {
+ return new MapGraph<>();
+ }
+
+ @Override
+ public void add(V vertex) {
+ check(vertex);
+ edges.computeIfAbsent(vertex, v -> new TreeMap<>());
+ edges.forEach((v, adj) -> adj.remove(vertex));
+ edges.get(vertex).clear();
+ }
+
+ @Override
+ public boolean contains(V vertex) {
+ check(vertex);
+ return edges.containsKey(vertex);
+ }
+
+ @Override
+ public void remove(V vertex) {
+ checkVert(vertex);
+ edges.remove(vertex);
+ edges.forEach((v, map) -> map.remove(vertex));
+ }
+
+ @Override
+ public int addEdge(V vertex1, V vertex2, int weight) {
+ checkVert(vertex1, vertex2);
+ Map edge = edges.get(vertex1);
+ Integer old = edge.get(vertex2);
+ old = old == null ? NO_EDGE : old;
+
+ if (weight == NO_EDGE)
+ edge.remove(vertex2);
+ else
+ edge.put(vertex2, weight);
+ return old;
+ }
+
+ @Override
+ public int getWeight(V vertex1, V vertex2) {
+ checkVert(vertex1, vertex2);
+ Integer weight = edges.get(vertex1).get(vertex2);
+ return weight == null ? NO_EDGE : weight;
+ }
+
+ @Override
+ public Set getChildren(V vertex) throws NullPointerException, IllegalArgumentException {
+ checkVert(vertex);
+ return new HashSet<>(edges.get(vertex).keySet());
+ }
+
+ @Override
+ public Set getAncestors(V vertex) throws NullPointerException, IllegalArgumentException {
+ checkVert(vertex);
+ Set ancestors = getDefaultSet();
+ edges.forEach((v, adj) -> {
+ if (adj.containsKey(vertex))
+ ancestors.add(v);
+ });
+ return ancestors;
+ }
+
+ @Override
+ public void removeAll() {
+ edges.clear();
+ }
+
+ @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();
+ }
+}
diff --git a/src/berack96/lib/graph/impl/MatrixGraph.java b/src/main/java/berack96/lib/graph/impl/MatrixGraph.java
similarity index 87%
rename from src/berack96/lib/graph/impl/MatrixGraph.java
rename to src/main/java/berack96/lib/graph/impl/MatrixGraph.java
index 6023d32..b0debc1 100644
--- a/src/berack96/lib/graph/impl/MatrixGraph.java
+++ b/src/main/java/berack96/lib/graph/impl/MatrixGraph.java
@@ -1,196 +1,196 @@
-package berack96.lib.graph.impl;
-
-import berack96.lib.graph.Graph;
-import berack96.lib.graph.GraphDirected;
-
-import java.util.*;
-
-/**
- * An implementation of the graph using a matrix for representing the edges
- *
- * @param the vertex
- * @author Berack96
- */
-public class MatrixGraph extends GraphDirected {
-
- private final Map map = new HashMap<>();
- private int[][] matrix = new int[0][0];
-
- @Override
- public Iterator iterator() {
- return map.keySet().iterator();
- }
-
- @Override
- protected Graph getNewInstance() {
- return new MatrixGraph<>();
- }
-
- @Override
- public void add(V vertex) {
- check(vertex);
- if (map.containsKey(vertex))
- removeAllEdge(vertex);
- else {
- map.put(vertex, map.size());
- matrix = modifyMatrix(map.size());
- }
- }
-
- @Override
- public boolean contains(V vertex) {
- check(vertex);
- return map.containsKey(vertex);
- }
-
- @Override
- public void remove(V vertex) {
- checkVert(vertex);
- int x = map.remove(vertex);
- int newSize = map.size();
-
- int[][] newMatrix = new int[newSize][newSize];
- for (int i = 0; i < newSize; i++)
- for (int j = 0; j < newSize; j++) {
- int indexI = i + (i < x ? 0 : 1);
- int indexJ = j + (j < x ? 0 : 1);
-
- newMatrix[i][j] = matrix[indexI][indexJ];
- }
-
- matrix = newMatrix;
- map.replaceAll((vert, index) -> index > x ? index - 1 : index);
- }
-
- @Override
- public int addEdge(V vertex1, V vertex2, int weight) {
- checkVert(vertex1, vertex2);
- int i = map.get(vertex1);
- int j = map.get(vertex2);
-
- int old = matrix[i][j];
- matrix[i][j] = weight;
- return old;
- }
-
- @Override
- public int getWeight(V vertex1, V vertex2) {
- checkVert(vertex1, vertex2);
- return matrix[map.get(vertex1)][map.get(vertex2)];
- }
-
- @Override
- public Collection getChildren(V vertex) throws NullPointerException, IllegalArgumentException {
- checkVert(vertex);
- int x = map.get(vertex);
- Collection children = new HashSet<>();
- Map invert = getInverted();
-
- for (int i = 0; i < matrix.length; i++)
- if (matrix[x][i] != NO_EDGE)
- children.add(invert.get(i));
- return children;
- }
-
- @Override
- public Collection getAncestors(V vertex) throws NullPointerException, IllegalArgumentException {
- checkVert(vertex);
- int x = map.get(vertex);
- Collection ancestors = new HashSet<>();
- Map invert = getInverted();
-
- for (int i = 0; i < matrix.length; i++)
- if (matrix[i][x] != NO_EDGE)
- ancestors.add(invert.get(i));
- return ancestors;
- }
-
- /**
- * From here on there are some optimization for the methods of the generic DirectedGraph
- **/
-
- @Override
- public int size() {
- return map.size();
- }
-
- @Override
- public int numberOfEdges() {
- int sum = 0;
- for (int[] adj : matrix)
- for (int edge : adj)
- if (edge != NO_EDGE)
- sum++;
- return sum;
- }
-
- @Override
- public int degreeIn(V vertex) throws NullPointerException, IllegalArgumentException {
- checkVert(vertex);
- int degree = 0, x = map.get(vertex);
- for (int[] ints : matrix) degree += ints[x] == NO_EDGE ? 0 : 1;
- return degree;
- }
-
- @Override
- public int degreeOut(V vertex) throws NullPointerException, IllegalArgumentException {
- checkVert(vertex);
- int degree = 0, x = map.get(vertex);
- for (int ints : matrix[x]) degree += ints == NO_EDGE ? 0 : 1;
- return degree;
- }
-
- @Override
- public void removeAllEdge(V vertex) throws NullPointerException, IllegalArgumentException {
- checkVert(vertex);
- int x = map.get(vertex);
- Arrays.fill(matrix[x], NO_EDGE);
- for (int[] ints : matrix) ints[x] = NO_EDGE;
- }
-
- @Override
- public void removeAllEdge() {
- for (int[] ints : matrix)
- Arrays.fill(ints, NO_EDGE);
- }
-
- @Override
- public void removeAll() {
- map.clear();
- matrix = new int[0][0];
- }
-
- @Override
- public void addAll(Collection vertices) throws NullPointerException {
- check(vertices);
- for (V vert : vertices)
- if (vert != null)
- map.compute(vert, (v, i) -> {
- if (i == null)
- return map.size();
- removeAllEdge(vert);
- return i;
- });
- matrix = modifyMatrix(map.size());
- }
-
- private int[][] modifyMatrix(int newSize) {
- int oldSize = matrix.length;
- if (newSize <= oldSize)
- return matrix;
-
- int[][] newMatrix = new int[newSize][newSize];
- for (int[] ints : newMatrix)
- Arrays.fill(ints, NO_EDGE);
- for (int i = 0; i < oldSize; i++)
- System.arraycopy(matrix[i], 0, newMatrix[i], 0, oldSize);
-
- return newMatrix;
- }
-
- private Map getInverted() {
- Map invert = new HashMap<>(map.size() + 1, 1);
- map.forEach((v, i) -> invert.put(i, v));
- return invert;
- }
-}
+package berack96.lib.graph.impl;
+
+import berack96.lib.graph.Graph;
+import berack96.lib.graph.GraphDirected;
+
+import java.util.*;
+
+/**
+ * An implementation of the graph using a matrix for representing the edges
+ *
+ * @param the vertex
+ * @author Berack96
+ */
+public class MatrixGraph extends GraphDirected {
+
+ private final Map map = getDefaultMap();
+ private int[][] matrix = new int[0][0];
+
+ @Override
+ public Iterator iterator() {
+ return map.keySet().iterator();
+ }
+
+ @Override
+ protected Graph getNewInstance() {
+ return new MatrixGraph<>();
+ }
+
+ @Override
+ public void add(V vertex) {
+ check(vertex);
+ if (map.containsKey(vertex))
+ removeAllEdge(vertex);
+ else {
+ map.put(vertex, map.size());
+ matrix = modifyMatrix(map.size());
+ }
+ }
+
+ @Override
+ public boolean contains(V vertex) {
+ check(vertex);
+ return map.containsKey(vertex);
+ }
+
+ @Override
+ public void remove(V vertex) {
+ checkVert(vertex);
+ int x = map.remove(vertex);
+ int newSize = map.size();
+
+ int[][] newMatrix = new int[newSize][newSize];
+ for (int i = 0; i < newSize; i++)
+ for (int j = 0; j < newSize; j++) {
+ int indexI = i + (i < x ? 0 : 1);
+ int indexJ = j + (j < x ? 0 : 1);
+
+ newMatrix[i][j] = matrix[indexI][indexJ];
+ }
+
+ matrix = newMatrix;
+ map.replaceAll((vert, index) -> index > x ? index - 1 : index);
+ }
+
+ @Override
+ public int addEdge(V vertex1, V vertex2, int weight) {
+ checkVert(vertex1, vertex2);
+ int i = map.get(vertex1);
+ int j = map.get(vertex2);
+
+ int old = matrix[i][j];
+ matrix[i][j] = weight;
+ return old;
+ }
+
+ @Override
+ public int getWeight(V vertex1, V vertex2) {
+ checkVert(vertex1, vertex2);
+ return matrix[map.get(vertex1)][map.get(vertex2)];
+ }
+
+ @Override
+ public Set getChildren(V vertex) throws NullPointerException, IllegalArgumentException {
+ checkVert(vertex);
+ int x = map.get(vertex);
+ Set children = getDefaultSet();
+ Map invert = getInverted();
+
+ for (int i = 0; i < matrix.length; i++)
+ if (matrix[x][i] != NO_EDGE)
+ children.add(invert.get(i));
+ return children;
+ }
+
+ @Override
+ public Set getAncestors(V vertex) throws NullPointerException, IllegalArgumentException {
+ checkVert(vertex);
+ int x = map.get(vertex);
+ Set ancestors = getDefaultSet();
+ Map invert = getInverted();
+
+ for (int i = 0; i < matrix.length; i++)
+ if (matrix[i][x] != NO_EDGE)
+ ancestors.add(invert.get(i));
+ return ancestors;
+ }
+
+ /**
+ * From here on there are some optimization for the methods of the generic DirectedGraph
+ **/
+
+ @Override
+ public int size() {
+ return map.size();
+ }
+
+ @Override
+ public int numberOfEdges() {
+ int sum = 0;
+ for (int[] adj : matrix)
+ for (int edge : adj)
+ if (edge != NO_EDGE)
+ sum++;
+ return sum;
+ }
+
+ @Override
+ public int degreeIn(V vertex) throws NullPointerException, IllegalArgumentException {
+ checkVert(vertex);
+ int degree = 0, x = map.get(vertex);
+ for (int[] ints : matrix) degree += ints[x] == NO_EDGE ? 0 : 1;
+ return degree;
+ }
+
+ @Override
+ public int degreeOut(V vertex) throws NullPointerException, IllegalArgumentException {
+ checkVert(vertex);
+ int degree = 0, x = map.get(vertex);
+ for (int ints : matrix[x]) degree += ints == NO_EDGE ? 0 : 1;
+ return degree;
+ }
+
+ @Override
+ public void removeAllEdge(V vertex) throws NullPointerException, IllegalArgumentException {
+ checkVert(vertex);
+ int x = map.get(vertex);
+ Arrays.fill(matrix[x], NO_EDGE);
+ for (int[] ints : matrix) ints[x] = NO_EDGE;
+ }
+
+ @Override
+ public void removeAllEdge() {
+ for (int[] ints : matrix)
+ Arrays.fill(ints, NO_EDGE);
+ }
+
+ @Override
+ public void removeAll() {
+ map.clear();
+ matrix = new int[0][0];
+ }
+
+ @Override
+ public void addAll(Collection vertices) throws NullPointerException {
+ check(vertices);
+ for (V vert : vertices)
+ if (vert != null)
+ map.compute(vert, (v, i) -> {
+ if (i == null)
+ return map.size();
+ removeAllEdge(vert);
+ return i;
+ });
+ matrix = modifyMatrix(map.size());
+ }
+
+ private int[][] modifyMatrix(int newSize) {
+ int oldSize = matrix.length;
+ if (newSize <= oldSize)
+ return matrix;
+
+ int[][] newMatrix = new int[newSize][newSize];
+ for (int[] ints : newMatrix)
+ Arrays.fill(ints, NO_EDGE);
+ for (int i = 0; i < oldSize; i++)
+ System.arraycopy(matrix[i], 0, newMatrix[i], 0, oldSize);
+
+ return newMatrix;
+ }
+
+ private Map getInverted() {
+ Map invert = getDefaultMap();
+ map.forEach((v, i) -> invert.put(i, v));
+ return invert;
+ }
+}
diff --git a/src/berack96/lib/graph/impl/MatrixUndGraph.java b/src/main/java/berack96/lib/graph/impl/MatrixUndGraph.java
similarity index 83%
rename from src/berack96/lib/graph/impl/MatrixUndGraph.java
rename to src/main/java/berack96/lib/graph/impl/MatrixUndGraph.java
index 327af48..459a871 100644
--- a/src/berack96/lib/graph/impl/MatrixUndGraph.java
+++ b/src/main/java/berack96/lib/graph/impl/MatrixUndGraph.java
@@ -8,7 +8,7 @@ import java.util.*;
public class MatrixUndGraph extends GraphUndirected {
- Map map = new HashMap<>();
+ Map map = getDefaultMap();
private int[][] matrix = new int[0][0];
@Override
@@ -73,33 +73,33 @@ public class MatrixUndGraph extends GraphUndirected {
}
@Override
- public Collection getChildren(V vertex) throws NullPointerException, IllegalArgumentException {
+ public Set getChildren(V vertex) throws NullPointerException, IllegalArgumentException {
checkVert(vertex);
- Collection collection = new HashSet<>();
- Map inverted = getInverted();
+ V[] inverted = getInverted();
+ Set set = getDefaultSet();
int x = map.get(vertex);
for (int i = 0; i < matrix.length; i++)
if (i < x && matrix[x][i] != 0)
- collection.add(inverted.get(i));
+ set.add(inverted[i]);
else if (i > x && matrix[i][x] != 0)
- collection.add(inverted.get(i));
- return collection;
+ set.add(inverted[i]);
+ return set;
}
@Override
- public Collection getAncestors(V vertex) throws NullPointerException, IllegalArgumentException {
+ public Set getAncestors(V vertex) throws NullPointerException, IllegalArgumentException {
return getChildren(vertex);
}
@Override
- public Collection> edges() {
- Map inverted = getInverted();
- Collection> edges = new LinkedList<>();
+ public Set> edges() {
+ V[] inverted = getInverted();
+ Set> edges = getDefaultSet();
for (int i = 0; i < matrix.length; i++)
for (int j = 0; j < matrix[i].length; j++)
if (matrix[i][j] != NO_EDGE)
- edges.add(new Edge<>(inverted.get(i), inverted.get(j), matrix[i][j]));
+ edges.add(new Edge<>(inverted[i], inverted[j], matrix[i][j]));
return edges;
}
@@ -168,9 +168,10 @@ public class MatrixUndGraph extends GraphUndirected {
return newMatrix;
}
- private Map getInverted() {
- Map invert = new HashMap<>(map.size() + 1, 1);
- map.forEach((v, i) -> invert.put(i, v));
+ @SuppressWarnings("unchecked")
+ private V[] getInverted() {
+ V[] invert = (V[]) new Object[map.size()];
+ map.forEach((v, i) -> invert[i] = v);
return invert;
}
}
diff --git a/src/berack96/lib/graph/models/EdgeSaveStructure.java b/src/main/java/berack96/lib/graph/models/EdgeSaveStructure.java
similarity index 95%
rename from src/berack96/lib/graph/models/EdgeSaveStructure.java
rename to src/main/java/berack96/lib/graph/models/EdgeSaveStructure.java
index e8b161d..b775ab2 100644
--- a/src/berack96/lib/graph/models/EdgeSaveStructure.java
+++ b/src/main/java/berack96/lib/graph/models/EdgeSaveStructure.java
@@ -1,18 +1,18 @@
-package berack96.lib.graph.models;
-
-/**
- * Support class used for saving a Graph in a file.
- *
- * @author Berack96
- */
-public class EdgeSaveStructure {
- protected EdgeSaveStructure(String s, String d, int w) {
- this.src = s;
- this.dest = d;
- this.weight = w;
- }
-
- public String src;
- public String dest;
- public int weight;
+package berack96.lib.graph.models;
+
+/**
+ * Support class used for saving a Graph in a file.
+ *
+ * @author Berack96
+ */
+public class EdgeSaveStructure {
+ protected EdgeSaveStructure(String s, String d, int w) {
+ this.src = s;
+ this.dest = d;
+ this.weight = w;
+ }
+
+ public String src;
+ public String dest;
+ public int weight;
}
\ No newline at end of file
diff --git a/src/berack96/lib/graph/models/GraphSaveStructure.java b/src/main/java/berack96/lib/graph/models/GraphSaveStructure.java
similarity index 92%
rename from src/berack96/lib/graph/models/GraphSaveStructure.java
rename to src/main/java/berack96/lib/graph/models/GraphSaveStructure.java
index 4d2cc4f..526e9ef 100644
--- a/src/berack96/lib/graph/models/GraphSaveStructure.java
+++ b/src/main/java/berack96/lib/graph/models/GraphSaveStructure.java
@@ -1,105 +1,105 @@
-package berack96.lib.graph.models;
-
-import berack96.lib.graph.Edge;
-import berack96.lib.graph.Graph;
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import com.google.gson.InstanceCreator;
-import com.google.gson.JsonSyntaxException;
-import com.google.gson.stream.JsonReader;
-
-import java.io.*;
-
-/**
- * Support class used for saving a Graph in a file.
- *
- * @author Berack96
- */
-public class GraphSaveStructure {
- final static public Gson gson = new Gson();
- public String[] vertices;
- public EdgeSaveStructure[] edges;
- //public MarkSaveStructure[] marks;
-
- /**
- * Load the graph saved in this class in an instance of a graph passed.
- * Before loading the graph, it is emptied.
- *
- * @param graph the graph where insert the data
- * @param fileName the file path and name
- * @param classV the class of the vertices
- * @throws FileNotFoundException in the case the file is not found
- * @throws NullPointerException in the case the graph is null
- */
- public final void load(@SuppressWarnings("ConstantConditions") Graph graph, String fileName, Class classV) throws FileNotFoundException, NullPointerException {
- //this way i use this class for the load
- InstanceCreator> creator = type -> this;
- Gson gson = new GsonBuilder().registerTypeAdapter(this.getClass(), creator).create();
- JsonReader reader = new JsonReader(new FileReader(fileName));
- gson.fromJson(reader, GraphSaveStructure.class);
- loadGraph(graph, classV);
- }
-
- /**
- * This method can be used by sub-classes for saving other stuff from the graph
- *
- * @param graph the graph to load with
- * @param classV the class used for the Vertex
- * @throws NullPointerException if the graph is null
- * @throws JsonSyntaxException if the file is malformed or corrupted
- */
- protected void loadGraph(Graph graph, Class classV) throws NullPointerException, JsonSyntaxException {
- graph.removeAll();
- for (String str : vertices)
- graph.add(gson.fromJson(str, classV));
-
- for (EdgeSaveStructure edge : edges)
- graph.addEdge(gson.fromJson(edge.src, classV), gson.fromJson(edge.dest, classV), edge.weight);
- }
-
- /**
- * Save the Graph passed as input to a file inserted as parameter.
- * The resulting file is a Json string representing all the graph.
- * If the directory for getting through the file do not exist,
- * then it is created.
- * Marks are not included.
- * The additional parameter is used if you want to save other as well as the graph.
- *
- * @param graph the graph to save
- * @param file the name of the file
- * @throws IOException for various reason that appear in the message, but the most common is that the file is not found.
- */
- public final void save(Graph graph, String file) throws IOException {
- saveGraph(graph);
- int slash = file.lastIndexOf("\\");
- if (slash == -1)
- slash = file.lastIndexOf("/");
- if (slash != -1) {
- String dir = file.substring(0, slash);
- File fDir = new File(dir);
- //noinspection ResultOfMethodCallIgnored
- fDir.mkdirs();
- }
-
- FileWriter writer = new FileWriter(file);
- gson.toJson(this, writer);
- writer.close();
- }
-
- /**
- * This method can be used by sub-classes for saving other stuff from the graph
- *
- * @param graph the graph to save
- */
- protected void saveGraph(Graph graph) {
- this.vertices = new String[graph.size()];
- int i = 0;
- for (Object o : graph.vertices())
- this.vertices[i++] = gson.toJson(o);
-
- this.edges = new EdgeSaveStructure[graph.numberOfEdges()];
- i = 0;
- for (Edge edge : graph.edges())
- this.edges[i++] = new EdgeSaveStructure(gson.toJson(edge.getSource()), gson.toJson(edge.getDestination()), edge.getWeight());
- }
+package berack96.lib.graph.models;
+
+import berack96.lib.graph.Edge;
+import berack96.lib.graph.Graph;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.InstanceCreator;
+import com.google.gson.JsonSyntaxException;
+import com.google.gson.stream.JsonReader;
+
+import java.io.*;
+
+/**
+ * Support class used for saving a Graph in a file.
+ *
+ * @author Berack96
+ */
+public class GraphSaveStructure {
+ final static public Gson gson = new Gson();
+ public String[] vertices;
+ public EdgeSaveStructure[] edges;
+ //public MarkSaveStructure[] marks;
+
+ /**
+ * Load the graph saved in this class in an instance of a graph passed.
+ * Before loading the graph, it is emptied.
+ *
+ * @param graph the graph where insert the data
+ * @param fileName the file path and name
+ * @param classV the class of the vertices
+ * @throws FileNotFoundException in the case the file is not found
+ * @throws NullPointerException in the case the graph is null
+ */
+ public final void load(Graph graph, String fileName, Class classV) throws FileNotFoundException, NullPointerException {
+ //this way i use this class for the load
+ InstanceCreator> creator = type -> this;
+ Gson gson = new GsonBuilder().registerTypeAdapter(this.getClass(), creator).create();
+ JsonReader reader = new JsonReader(new FileReader(fileName));
+ gson.fromJson(reader, GraphSaveStructure.class);
+ loadGraph(graph, classV);
+ }
+
+ /**
+ * This method can be used by sub-classes for saving other stuff from the graph
+ *
+ * @param graph the graph to load with
+ * @param classV the class used for the Vertex
+ * @throws NullPointerException if the graph is null
+ * @throws JsonSyntaxException if the file is malformed or corrupted
+ */
+ protected void loadGraph(Graph graph, Class classV) throws NullPointerException, JsonSyntaxException {
+ graph.removeAll();
+ for (String str : vertices)
+ graph.add(gson.fromJson(str, classV));
+
+ for (EdgeSaveStructure edge : edges)
+ graph.addEdge(gson.fromJson(edge.src, classV), gson.fromJson(edge.dest, classV), edge.weight);
+ }
+
+ /**
+ * Save the Graph passed as input to a file inserted as parameter.
+ * The resulting file is a Json string representing all the graph.
+ * If the directory for getting through the file do not exist,
+ * then it is created.
+ * Marks are not included.
+ * The additional parameter is used if you want to save other as well as the graph.
+ *
+ * @param graph the graph to save
+ * @param file the name of the file
+ * @throws IOException for various reason that appear in the message, but the most common is that the file is not found.
+ */
+ public final void save(Graph graph, String file) throws IOException {
+ saveGraph(graph);
+ int slash = file.lastIndexOf("\\");
+ if (slash == -1)
+ slash = file.lastIndexOf("/");
+ if (slash != -1) {
+ String dir = file.substring(0, slash);
+ File fDir = new File(dir);
+ //noinspection ResultOfMethodCallIgnored
+ fDir.mkdirs();
+ }
+
+ FileWriter writer = new FileWriter(file);
+ gson.toJson(this, writer);
+ writer.close();
+ }
+
+ /**
+ * This method can be used by sub-classes for saving other stuff from the graph
+ *
+ * @param graph the graph to save
+ */
+ protected void saveGraph(Graph graph) {
+ this.vertices = new String[graph.size()];
+ int i = 0;
+ for (Object o : graph.vertices())
+ this.vertices[i++] = gson.toJson(o);
+
+ this.edges = new EdgeSaveStructure[graph.numberOfEdges()];
+ i = 0;
+ for (Edge edge : graph.edges())
+ this.edges[i++] = new EdgeSaveStructure(gson.toJson(edge.getSource()), gson.toJson(edge.getDestination()), edge.getWeight());
+ }
}
\ No newline at end of file
diff --git a/src/berack96/lib/graph/models/MarkSaveStructure.java b/src/main/java/berack96/lib/graph/models/MarkSaveStructure.java
similarity index 94%
rename from src/berack96/lib/graph/models/MarkSaveStructure.java
rename to src/main/java/berack96/lib/graph/models/MarkSaveStructure.java
index 3b3c125..3e4ba2b 100644
--- a/src/berack96/lib/graph/models/MarkSaveStructure.java
+++ b/src/main/java/berack96/lib/graph/models/MarkSaveStructure.java
@@ -1,17 +1,17 @@
-package berack96.lib.graph.models;
-
-/**
- * Support class used for saving a Graph in a file.
- *
- * @author Berack96
- *
- */
-public class MarkSaveStructure {
- protected MarkSaveStructure(String v, Object m) {
- this.vert = v;
- this.mark = m;
- }
-
- public String vert;
- public Object mark;
-}
+package berack96.lib.graph.models;
+
+/**
+ * Support class used for saving a Graph in a file.
+ *
+ * @author Berack96
+ *
+ */
+public class MarkSaveStructure {
+ protected MarkSaveStructure(String v, Object m) {
+ this.vert = v;
+ this.mark = m;
+ }
+
+ public String vert;
+ public Object mark;
+}
diff --git a/src/berack96/lib/graph/struct/QuickFind.java b/src/main/java/berack96/lib/graph/struct/QuickFind.java
similarity index 85%
rename from src/berack96/lib/graph/struct/QuickFind.java
rename to src/main/java/berack96/lib/graph/struct/QuickFind.java
index 51cc7de..a2345b7 100644
--- a/src/berack96/lib/graph/struct/QuickFind.java
+++ b/src/main/java/berack96/lib/graph/struct/QuickFind.java
@@ -1,19 +1,20 @@
package berack96.lib.graph.struct;
import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
import java.util.Map;
+import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function;
+import berack96.lib.graph.Graph;
+
/**
* Simple implementation of the {@link UnionFind} interface with priority to the find function.
*
* @param the elements to search and merge
*/
public class QuickFind implements UnionFind {
- Map> struct = new HashMap<>();
+ Map> struct = Graph.getDefaultMap();
@Override
public int size() {
@@ -22,7 +23,7 @@ public class QuickFind implements UnionFind {
@Override
public void makeSetAll(Collection elements) throws NullPointerException {
- Map> temp = new HashMap<>(elements.size() + 1, 1);
+ Map> temp = Graph.getDefaultMap();
for (X elem : elements)
temp.computeIfAbsent(elem, new AddElement());
struct.putAll(temp);
@@ -65,10 +66,10 @@ public class QuickFind implements UnionFind {
/**
* Stupid class for implementing the adding of a new element
*/
- private class AddElement implements Function