Refactoring

- changed to maven
- modified hashMap and HashSet to Tree
- modified files path
This commit is contained in:
2022-08-30 11:12:50 +02:00
parent 9bda59dc7b
commit 07305b82f8
52 changed files with 1547 additions and 1486 deletions

5
.gitignore vendored
View File

@@ -125,8 +125,9 @@ local.properties
# mine # mine
target/
.idea/* .idea/*
.project .project
*.iml *.iml
.classpath .classpath
/.gradle/ /.gradle/

View File

@@ -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'
}

80
pom.xml Normal file
View File

@@ -0,0 +1,80 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>berack96</groupId>
<artifactId>Graph</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.9.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<version>5.9.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.9.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.2</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>berack96.lib.graph.view.Main</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<executions>
<execution>
<id>attach-javadocs</id>
<phase>prepare-package</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
</project>

View File

@@ -4,10 +4,8 @@ import berack96.lib.graph.visit.VisitSCC;
import berack96.lib.graph.visit.VisitTopological; import berack96.lib.graph.visit.VisitTopological;
import berack96.lib.graph.visit.impl.Tarjan; 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.List;
import java.util.Set;
/** /**
* This is a more specific interface for an implementation of a Undirected Graph.<br> * This is a more specific interface for an implementation of a Undirected Graph.<br>
@@ -70,17 +68,17 @@ public abstract class GraphDirected<V> extends Graph<V> {
/** /**
* Retrieve all the edges of a particular vertex.<br> * Retrieve all the edges of a particular vertex.<br>
* Note: the edges that are returned are the one that have this vertex as destination and another as source.<br> * Note: the edges that are returned are the one that have this vertex as destination and another as source.<br>
* Note2: depending on the implementation, modifying the returned collection<br> * Note2: depending on the implementation, modifying the returned Set<br>
* could affect the graph behavior and the changes could be reflected to the graph. * could affect the graph behavior and the changes could be reflected to the graph.
* *
* @param vertex a vertex of 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 NullPointerException if the vertex is null
* @throws IllegalArgumentException if the vertex is not contained in the graph * @throws IllegalArgumentException if the vertex is not contained in the graph
*/ */
public Collection<Edge<V>> getEdgesIn(V vertex) throws NullPointerException, IllegalArgumentException { public Set<Edge<V>> getEdgesIn(V vertex) throws NullPointerException, IllegalArgumentException {
Collection<V> ancestors = getAncestors(vertex); Set<V> ancestors = getAncestors(vertex);
Collection<Edge<V>> edgesIn = new HashSet<>(ancestors.size()); Set<Edge<V>> edgesIn = getDefaultSet();
for (V ancestor : ancestors) { for (V ancestor : ancestors) {
int weight = getWeight(ancestor, vertex); int weight = getWeight(ancestor, vertex);
@@ -93,17 +91,17 @@ public abstract class GraphDirected<V> extends Graph<V> {
/** /**
* Retrieve all the edges that goes OUT of a particular vertex.<br> * Retrieve all the edges that goes OUT of a particular vertex.<br>
* Note: the edges that are returned are the one that have this vertex as source and another one as destination.<br> * Note: the edges that are returned are the one that have this vertex as source and another one as destination.<br>
* Note2: depending on the implementation, modifying the returned collection<br> * Note2: depending on the implementation, modifying the returned Set<br>
* could affect the graph behavior and the changes could be reflected to the graph. * could affect the graph behavior and the changes could be reflected to the graph.
* *
* @param vertex a vertex of 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 NullPointerException if the vertex is null
* @throws IllegalArgumentException if the vertex is not contained in the graph * @throws IllegalArgumentException if the vertex is not contained in the graph
*/ */
public Collection<Edge<V>> getEdgesOut(V vertex) throws NullPointerException, IllegalArgumentException { public Set<Edge<V>> getEdgesOut(V vertex) throws NullPointerException, IllegalArgumentException {
Collection<V> children = getChildren(vertex); Set<V> children = getChildren(vertex);
Collection<Edge<V>> edgesOut = new HashSet<>(children.size()); Set<Edge<V>> edgesOut = getDefaultSet();
for (V child : children) { for (V child : children) {
int weight = getWeight(vertex, child); int weight = getWeight(vertex, child);
@@ -178,26 +176,26 @@ public abstract class GraphDirected<V> extends Graph<V> {
* The strongly connected components or disconnected components of an arbitrary directed graph * The strongly connected components or disconnected components of an arbitrary directed graph
* form a partition into subgraphs that are themselves strongly connected. * 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<Collection<V>> stronglyConnectedComponents() { public final Set<Set<V>> stronglyConnectedComponents() {
VisitSCC<V> visit = new Tarjan<>(); VisitSCC<V> visit = new Tarjan<>();
visit.visit(this, null, null); visit.visit(this, null, null);
return visit.getSCC(); return visit.getSCC();
} }
@Override @Override
public Collection<Edge<V>> edgesOf(V vertex) throws NullPointerException, IllegalArgumentException { public Set<Edge<V>> edgesOf(V vertex) throws NullPointerException, IllegalArgumentException {
Collection<Edge<V>> edges = getEdgesIn(vertex); Set<Edge<V>> edges = getEdgesIn(vertex);
edges.addAll(getEdgesOut(vertex)); edges.addAll(getEdgesOut(vertex));
return edges; return edges;
} }
@Override @Override
public Collection<Edge<V>> edges() { public Set<Edge<V>> edges() {
Collection<Edge<V>> collection = new ArrayList<>(); Set<Edge<V>> set = getDefaultSet();
forEach(v -> collection.addAll(getEdgesIn(v))); forEach(v -> set.addAll(getEdgesIn(v)));
return collection; return set;
} }
@Override @Override

View File

@@ -3,8 +3,7 @@ package berack96.lib.graph;
import berack96.lib.graph.visit.VisitMST; import berack96.lib.graph.visit.VisitMST;
import berack96.lib.graph.visit.impl.Prim; import berack96.lib.graph.visit.impl.Prim;
import java.util.Collection; import java.util.Set;
import java.util.LinkedList;
/** /**
* This is a more specific interface for an implementation of a Directed Graph.<br> * This is a more specific interface for an implementation of a Directed Graph.<br>
@@ -19,27 +18,27 @@ public abstract class GraphUndirected<V> extends Graph<V> {
/** /**
* The connected components of an arbitrary undirected graph form a partition into subgraphs that are themselves connected. * 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<Collection<V>> connectedComponents() { public Set<Set<V>> connectedComponents() {
return null; return null;
} }
/** /**
* minimum spanning forest or minimum spamming tree of the graph * 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<Edge<V>> minimumSpanningForest() { public Set<Edge<V>> minimumSpanningForest() {
VisitMST<V> visit = new Prim<>(); VisitMST<V> visit = new Prim<>();
visit.visit(this, iterator().next(), null); visit.visit(this, iterator().next(), null);
return visit.getMST(); return visit.getMST();
} }
@Override @Override
public Collection<Edge<V>> edgesOf(V vertex) throws NullPointerException, IllegalArgumentException { public Set<Edge<V>> edgesOf(V vertex) throws NullPointerException, IllegalArgumentException {
checkVert(vertex); checkVert(vertex);
Collection<Edge<V>> edges = new LinkedList<>(); Set<Edge<V>> edges = getDefaultSet();
getChildren(vertex).forEach(v -> edges.add(new Edge<>(vertex, v, getWeight(vertex, v)))); getChildren(vertex).forEach(v -> edges.add(new Edge<>(vertex, v, getWeight(vertex, v))));
return edges; return edges;
} }

View File

@@ -0,0 +1,18 @@
package berack96.lib.graph;
import java.util.Comparator;
/**
* Compare two arbitrary objects.<br>
* It uses the method hashCode that every object has to compare two objects.<br>
* This is a simple use
*/
public class ObjectsComparator implements Comparator<Object> {
static public final ObjectsComparator instance = new ObjectsComparator();
private ObjectsComparator(){};
@Override
public int compare(Object o1, Object o2) {
return o1.hashCode() - o2.hashCode();
}
}

View File

@@ -1,160 +1,161 @@
package berack96.lib.graph.impl; package berack96.lib.graph.impl;
import berack96.lib.graph.Graph; import berack96.lib.graph.Graph;
import berack96.lib.graph.GraphDirected; import berack96.lib.graph.GraphDirected;
import java.util.*; import java.util.*;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
/** /**
* An implementation of the graph using an adjacent list for representing the edges * An implementation of the graph using an adjacent list for representing the edges
* *
* @param <V> the vertex * @param <V> the vertex
* @author Berack96 * @author Berack96
*/ */
public class ListGraph<V> extends GraphDirected<V> { public class ListGraph<V> extends GraphDirected<V> {
final private Map<V, List<Adj>> adj = new Hashtable<>(); // in case of thread safety use -> Collections.synchronizedSortedMap(TreeMap)
final private Map<V, List<Adj>> adj = getDefaultMap();
@Override
public Iterator<V> iterator() { @Override
return adj.keySet().iterator(); public Iterator<V> iterator() {
} return adj.keySet().iterator();
}
@Override
protected Graph<V> getNewInstance() { @Override
return new ListGraph<>(); protected Graph<V> getNewInstance() {
} return new ListGraph<>();
}
@Override
public void add(V vertex) { @Override
check(vertex); public void add(V vertex) {
if (adj.containsKey(vertex)) check(vertex);
removeAllEdge(vertex); if (adj.containsKey(vertex))
else removeAllEdge(vertex);
adj.put(vertex, new LinkedList<>()); else
} adj.put(vertex, new LinkedList<>());
}
@Override
public boolean contains(V vertex) { @Override
check(vertex); public boolean contains(V vertex) {
return adj.containsKey(vertex); check(vertex);
} return adj.containsKey(vertex);
}
@Override
public void remove(V vertex) { @Override
checkVert(vertex); public void remove(V vertex) {
adj.remove(vertex); checkVert(vertex);
adj.forEach((v, list) -> list.remove(getAdj(list, vertex))); adj.remove(vertex);
} adj.forEach((v, list) -> list.remove(getAdj(list, vertex)));
}
@Override
public int addEdge(V vertex1, V vertex2, int weight) { @Override
checkVert(vertex1, vertex2); public int addEdge(V vertex1, V vertex2, int weight) {
checkVert(vertex1, vertex2);
List<Adj> list = adj.get(vertex1);
Adj a = getAdj(list, vertex2); List<Adj> list = adj.get(vertex1);
int old = a == null ? NO_EDGE : a.weight; Adj a = getAdj(list, vertex2);
int old = a == null ? NO_EDGE : a.weight;
if (weight == NO_EDGE)
list.remove(a); if (weight == NO_EDGE)
else if (old == NO_EDGE) list.remove(a);
list.add(new Adj(vertex2, weight)); else if (old == NO_EDGE)
else list.add(new Adj(vertex2, weight));
a.weight = weight; else
return old; a.weight = weight;
} return old;
}
@Override
public int getWeight(V vertex1, V vertex2) { @Override
checkVert(vertex1, vertex2); public int getWeight(V vertex1, V vertex2) {
Adj a = getAdj(adj.get(vertex1), vertex2); checkVert(vertex1, vertex2);
return a == null ? NO_EDGE : a.weight; Adj a = getAdj(adj.get(vertex1), vertex2);
} return a == null ? NO_EDGE : a.weight;
}
@Override
public Collection<V> getChildren(V vertex) throws NullPointerException, IllegalArgumentException { @Override
checkVert(vertex); public Set<V> getChildren(V vertex) throws NullPointerException, IllegalArgumentException {
Collection<V> children = new HashSet<>(); checkVert(vertex);
for (Adj adj : adj.get(vertex)) Set<V> children = getDefaultSet();
children.add(adj.vertex); for (Adj adj : adj.get(vertex))
return children; children.add(adj.vertex);
} return children;
}
@Override
public Collection<V> getAncestors(V vertex) throws NullPointerException, IllegalArgumentException { @Override
checkVert(vertex); public Set<V> getAncestors(V vertex) throws NullPointerException, IllegalArgumentException {
Collection<V> ancestors = new HashSet<>(); checkVert(vertex);
adj.forEach((v, list) -> { Set<V> ancestors = getDefaultSet();
if (getAdj(list, vertex) != null) adj.forEach((v, list) -> {
ancestors.add(v); if (getAdj(list, vertex) != null)
}); ancestors.add(v);
});
return ancestors;
} return ancestors;
}
/**
* From here on there are some optimization for the methods of the generic DirectedGraph /**
**/ * From here on there are some optimization for the methods of the generic DirectedGraph
**/
@Override
public int size() { @Override
return adj.size(); public int size() {
} return adj.size();
}
@Override
public int numberOfEdges() { @Override
AtomicInteger size = new AtomicInteger(0); public int numberOfEdges() {
adj.values().forEach(list -> size.addAndGet(list.size())); AtomicInteger size = new AtomicInteger(0);
return size.get(); adj.values().forEach(list -> size.addAndGet(list.size()));
} return size.get();
}
@Override
public int degreeIn(V vertex) throws NullPointerException, IllegalArgumentException { @Override
checkVert(vertex); public int degreeIn(V vertex) throws NullPointerException, IllegalArgumentException {
AtomicInteger degree = new AtomicInteger(0); checkVert(vertex);
adj.values().forEach(list -> degree.addAndGet(getAdj(list, vertex) != null ? 1 : 0)); AtomicInteger degree = new AtomicInteger(0);
return degree.get(); adj.values().forEach(list -> degree.addAndGet(getAdj(list, vertex) != null ? 1 : 0));
} return degree.get();
}
@Override
public int degreeOut(V vertex) throws NullPointerException, IllegalArgumentException { @Override
checkVert(vertex); public int degreeOut(V vertex) throws NullPointerException, IllegalArgumentException {
return adj.get(vertex).size(); checkVert(vertex);
} return adj.get(vertex).size();
}
@Override
public void removeAllEdge(V vertex) throws NullPointerException, IllegalArgumentException { @Override
checkVert(vertex); public void removeAllEdge(V vertex) throws NullPointerException, IllegalArgumentException {
adj.get(vertex).clear(); checkVert(vertex);
adj.forEach((v, list) -> list.remove(getAdj(list, vertex))); adj.get(vertex).clear();
} adj.forEach((v, list) -> list.remove(getAdj(list, vertex)));
}
@Override
public void removeAllEdge() { @Override
adj.forEach((v, list) -> list.clear()); public void removeAllEdge() {
} adj.forEach((v, list) -> list.clear());
}
@Override
public void removeAll() { @Override
adj.clear(); public void removeAll() {
} adj.clear();
}
private Adj getAdj(List<Adj> list, V vertex) {
for (Adj adj : list) private Adj getAdj(List<Adj> list, V vertex) {
if (Objects.equals(adj.vertex, vertex)) for (Adj adj : list)
return adj; if (Objects.equals(adj.vertex, vertex))
return null; return adj;
} return null;
}
private class Adj {
private final V vertex; private class Adj {
private int weight; private final V vertex;
private int weight;
private Adj(V vertex, int weight) {
this.vertex = vertex; private Adj(V vertex, int weight) {
this.weight = weight; this.vertex = vertex;
} this.weight = weight;
} }
} }
}

View File

@@ -1,115 +1,116 @@
package berack96.lib.graph.impl; package berack96.lib.graph.impl;
import berack96.lib.graph.Graph; import berack96.lib.graph.Graph;
import berack96.lib.graph.GraphDirected; import berack96.lib.graph.GraphDirected;
import java.util.*; import java.util.*;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
/** /**
* Graph that uses HashMap for vertices and edges<br> * Graph that uses TreeMap for vertices and edges<br>
* More specifically it utilizes a Map containing all the vertices mapped to all their edges<br> * More specifically it utilizes a Map containing all the vertices mapped to all their edges<br>
* Technically this version of the graph combine the fast adding/removing of the edges of the Matrix implementation, * 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.<br> * with the low memory and fast adding/removing of vertices of the Linked List implementation.<br>
* This happen if the HashMap is not reallocated. So in the end each operation of adding or removing has O(n) * "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).<br>
* @param <V> the vertices *
* @author Berack96 * @param <V> the vertices
*/ * @author Berack96
public class MapGraph<V> extends GraphDirected<V> { */
public class MapGraph<V> extends GraphDirected<V> {
/**
* Map that contains the edges from a vertex to another<br> /**
* The first vertex is the vertex where start the edge, the second one is where the edge goes<br> * Map that contains the edges from a vertex to another<br>
* If an edge exist, then it's weight is returned * The first vertex is the vertex where start the edge, the second one is where the edge goes<br>
*/ * If an edge exist, then it's weight is returned
private final Map<V, Map<V, Integer>> edges = new HashMap<>(); */
private final Map<V, Map<V, Integer>> edges = getDefaultMap();
@Override
public Iterator<V> iterator() { @Override
return edges.keySet().iterator(); public Iterator<V> iterator() {
} return edges.keySet().iterator();
}
@Override
protected Graph<V> getNewInstance() { @Override
return new MapGraph<>(); protected Graph<V> getNewInstance() {
} return new MapGraph<>();
}
@Override
public void add(V vertex) { @Override
check(vertex); public void add(V vertex) {
edges.computeIfAbsent(vertex, v -> new HashMap<>()); check(vertex);
edges.forEach((v, adj) -> adj.remove(vertex)); edges.computeIfAbsent(vertex, v -> new TreeMap<>());
edges.get(vertex).clear(); edges.forEach((v, adj) -> adj.remove(vertex));
} edges.get(vertex).clear();
}
@Override
public boolean contains(V vertex) { @Override
check(vertex); public boolean contains(V vertex) {
return edges.containsKey(vertex); check(vertex);
} return edges.containsKey(vertex);
}
@Override
public void remove(V vertex) { @Override
checkVert(vertex); public void remove(V vertex) {
edges.remove(vertex); checkVert(vertex);
edges.forEach((v, map) -> map.remove(vertex)); edges.remove(vertex);
} edges.forEach((v, map) -> map.remove(vertex));
}
@Override
public int addEdge(V vertex1, V vertex2, int weight) { @Override
checkVert(vertex1, vertex2); public int addEdge(V vertex1, V vertex2, int weight) {
Map<V, Integer> edge = edges.get(vertex1); checkVert(vertex1, vertex2);
Integer old = edge.get(vertex2); Map<V, Integer> edge = edges.get(vertex1);
old = old == null ? NO_EDGE : old; Integer old = edge.get(vertex2);
old = old == null ? NO_EDGE : old;
if (weight == NO_EDGE)
edge.remove(vertex2); if (weight == NO_EDGE)
else edge.remove(vertex2);
edge.put(vertex2, weight); else
return old; edge.put(vertex2, weight);
} return old;
}
@Override
public int getWeight(V vertex1, V vertex2) { @Override
checkVert(vertex1, vertex2); public int getWeight(V vertex1, V vertex2) {
Integer weight = edges.get(vertex1).get(vertex2); checkVert(vertex1, vertex2);
return weight == null ? NO_EDGE : weight; Integer weight = edges.get(vertex1).get(vertex2);
} return weight == null ? NO_EDGE : weight;
}
@Override
public Collection<V> getChildren(V vertex) throws NullPointerException, IllegalArgumentException { @Override
checkVert(vertex); public Set<V> getChildren(V vertex) throws NullPointerException, IllegalArgumentException {
return new HashSet<>(edges.get(vertex).keySet()); checkVert(vertex);
} return new HashSet<>(edges.get(vertex).keySet());
}
@Override
public Collection<V> getAncestors(V vertex) throws NullPointerException, IllegalArgumentException { @Override
checkVert(vertex); public Set<V> getAncestors(V vertex) throws NullPointerException, IllegalArgumentException {
Collection<V> ancestors = new HashSet<>(); checkVert(vertex);
edges.forEach((v, adj) -> { Set<V> ancestors = getDefaultSet();
if (adj.containsKey(vertex)) edges.forEach((v, adj) -> {
ancestors.add(v); if (adj.containsKey(vertex))
}); ancestors.add(v);
return ancestors; });
} return ancestors;
}
@Override
public void removeAll() { @Override
edges.clear(); public void removeAll() {
} edges.clear();
}
@Override
public int size() { @Override
return edges.size(); public int size() {
} return edges.size();
}
@Override
public int numberOfEdges() { @Override
AtomicInteger sum = new AtomicInteger(0); public int numberOfEdges() {
edges.forEach((v, map) -> sum.getAndAdd(map.size())); AtomicInteger sum = new AtomicInteger(0);
edges.forEach((v, map) -> sum.getAndAdd(map.size()));
return sum.get();
} return sum.get();
} }
}

View File

@@ -1,196 +1,196 @@
package berack96.lib.graph.impl; package berack96.lib.graph.impl;
import berack96.lib.graph.Graph; import berack96.lib.graph.Graph;
import berack96.lib.graph.GraphDirected; import berack96.lib.graph.GraphDirected;
import java.util.*; import java.util.*;
/** /**
* An implementation of the graph using a matrix for representing the edges * An implementation of the graph using a matrix for representing the edges
* *
* @param <V> the vertex * @param <V> the vertex
* @author Berack96 * @author Berack96
*/ */
public class MatrixGraph<V> extends GraphDirected<V> { public class MatrixGraph<V> extends GraphDirected<V> {
private final Map<V, Integer> map = new HashMap<>(); private final Map<V, Integer> map = getDefaultMap();
private int[][] matrix = new int[0][0]; private int[][] matrix = new int[0][0];
@Override @Override
public Iterator<V> iterator() { public Iterator<V> iterator() {
return map.keySet().iterator(); return map.keySet().iterator();
} }
@Override @Override
protected Graph<V> getNewInstance() { protected Graph<V> getNewInstance() {
return new MatrixGraph<>(); return new MatrixGraph<>();
} }
@Override @Override
public void add(V vertex) { public void add(V vertex) {
check(vertex); check(vertex);
if (map.containsKey(vertex)) if (map.containsKey(vertex))
removeAllEdge(vertex); removeAllEdge(vertex);
else { else {
map.put(vertex, map.size()); map.put(vertex, map.size());
matrix = modifyMatrix(map.size()); matrix = modifyMatrix(map.size());
} }
} }
@Override @Override
public boolean contains(V vertex) { public boolean contains(V vertex) {
check(vertex); check(vertex);
return map.containsKey(vertex); return map.containsKey(vertex);
} }
@Override @Override
public void remove(V vertex) { public void remove(V vertex) {
checkVert(vertex); checkVert(vertex);
int x = map.remove(vertex); int x = map.remove(vertex);
int newSize = map.size(); int newSize = map.size();
int[][] newMatrix = new int[newSize][newSize]; int[][] newMatrix = new int[newSize][newSize];
for (int i = 0; i < newSize; i++) for (int i = 0; i < newSize; i++)
for (int j = 0; j < newSize; j++) { for (int j = 0; j < newSize; j++) {
int indexI = i + (i < x ? 0 : 1); int indexI = i + (i < x ? 0 : 1);
int indexJ = j + (j < x ? 0 : 1); int indexJ = j + (j < x ? 0 : 1);
newMatrix[i][j] = matrix[indexI][indexJ]; newMatrix[i][j] = matrix[indexI][indexJ];
} }
matrix = newMatrix; matrix = newMatrix;
map.replaceAll((vert, index) -> index > x ? index - 1 : index); map.replaceAll((vert, index) -> index > x ? index - 1 : index);
} }
@Override @Override
public int addEdge(V vertex1, V vertex2, int weight) { public int addEdge(V vertex1, V vertex2, int weight) {
checkVert(vertex1, vertex2); checkVert(vertex1, vertex2);
int i = map.get(vertex1); int i = map.get(vertex1);
int j = map.get(vertex2); int j = map.get(vertex2);
int old = matrix[i][j]; int old = matrix[i][j];
matrix[i][j] = weight; matrix[i][j] = weight;
return old; return old;
} }
@Override @Override
public int getWeight(V vertex1, V vertex2) { public int getWeight(V vertex1, V vertex2) {
checkVert(vertex1, vertex2); checkVert(vertex1, vertex2);
return matrix[map.get(vertex1)][map.get(vertex2)]; return matrix[map.get(vertex1)][map.get(vertex2)];
} }
@Override @Override
public Collection<V> getChildren(V vertex) throws NullPointerException, IllegalArgumentException { public Set<V> getChildren(V vertex) throws NullPointerException, IllegalArgumentException {
checkVert(vertex); checkVert(vertex);
int x = map.get(vertex); int x = map.get(vertex);
Collection<V> children = new HashSet<>(); Set<V> children = getDefaultSet();
Map<Integer, V> invert = getInverted(); Map<Integer, V> invert = getInverted();
for (int i = 0; i < matrix.length; i++) for (int i = 0; i < matrix.length; i++)
if (matrix[x][i] != NO_EDGE) if (matrix[x][i] != NO_EDGE)
children.add(invert.get(i)); children.add(invert.get(i));
return children; return children;
} }
@Override @Override
public Collection<V> getAncestors(V vertex) throws NullPointerException, IllegalArgumentException { public Set<V> getAncestors(V vertex) throws NullPointerException, IllegalArgumentException {
checkVert(vertex); checkVert(vertex);
int x = map.get(vertex); int x = map.get(vertex);
Collection<V> ancestors = new HashSet<>(); Set<V> ancestors = getDefaultSet();
Map<Integer, V> invert = getInverted(); Map<Integer, V> invert = getInverted();
for (int i = 0; i < matrix.length; i++) for (int i = 0; i < matrix.length; i++)
if (matrix[i][x] != NO_EDGE) if (matrix[i][x] != NO_EDGE)
ancestors.add(invert.get(i)); ancestors.add(invert.get(i));
return ancestors; return ancestors;
} }
/** /**
* From here on there are some optimization for the methods of the generic DirectedGraph * From here on there are some optimization for the methods of the generic DirectedGraph
**/ **/
@Override @Override
public int size() { public int size() {
return map.size(); return map.size();
} }
@Override @Override
public int numberOfEdges() { public int numberOfEdges() {
int sum = 0; int sum = 0;
for (int[] adj : matrix) for (int[] adj : matrix)
for (int edge : adj) for (int edge : adj)
if (edge != NO_EDGE) if (edge != NO_EDGE)
sum++; sum++;
return sum; return sum;
} }
@Override @Override
public int degreeIn(V vertex) throws NullPointerException, IllegalArgumentException { public int degreeIn(V vertex) throws NullPointerException, IllegalArgumentException {
checkVert(vertex); checkVert(vertex);
int degree = 0, x = map.get(vertex); int degree = 0, x = map.get(vertex);
for (int[] ints : matrix) degree += ints[x] == NO_EDGE ? 0 : 1; for (int[] ints : matrix) degree += ints[x] == NO_EDGE ? 0 : 1;
return degree; return degree;
} }
@Override @Override
public int degreeOut(V vertex) throws NullPointerException, IllegalArgumentException { public int degreeOut(V vertex) throws NullPointerException, IllegalArgumentException {
checkVert(vertex); checkVert(vertex);
int degree = 0, x = map.get(vertex); int degree = 0, x = map.get(vertex);
for (int ints : matrix[x]) degree += ints == NO_EDGE ? 0 : 1; for (int ints : matrix[x]) degree += ints == NO_EDGE ? 0 : 1;
return degree; return degree;
} }
@Override @Override
public void removeAllEdge(V vertex) throws NullPointerException, IllegalArgumentException { public void removeAllEdge(V vertex) throws NullPointerException, IllegalArgumentException {
checkVert(vertex); checkVert(vertex);
int x = map.get(vertex); int x = map.get(vertex);
Arrays.fill(matrix[x], NO_EDGE); Arrays.fill(matrix[x], NO_EDGE);
for (int[] ints : matrix) ints[x] = NO_EDGE; for (int[] ints : matrix) ints[x] = NO_EDGE;
} }
@Override @Override
public void removeAllEdge() { public void removeAllEdge() {
for (int[] ints : matrix) for (int[] ints : matrix)
Arrays.fill(ints, NO_EDGE); Arrays.fill(ints, NO_EDGE);
} }
@Override @Override
public void removeAll() { public void removeAll() {
map.clear(); map.clear();
matrix = new int[0][0]; matrix = new int[0][0];
} }
@Override @Override
public void addAll(Collection<V> vertices) throws NullPointerException { public void addAll(Collection<V> vertices) throws NullPointerException {
check(vertices); check(vertices);
for (V vert : vertices) for (V vert : vertices)
if (vert != null) if (vert != null)
map.compute(vert, (v, i) -> { map.compute(vert, (v, i) -> {
if (i == null) if (i == null)
return map.size(); return map.size();
removeAllEdge(vert); removeAllEdge(vert);
return i; return i;
}); });
matrix = modifyMatrix(map.size()); matrix = modifyMatrix(map.size());
} }
private int[][] modifyMatrix(int newSize) { private int[][] modifyMatrix(int newSize) {
int oldSize = matrix.length; int oldSize = matrix.length;
if (newSize <= oldSize) if (newSize <= oldSize)
return matrix; return matrix;
int[][] newMatrix = new int[newSize][newSize]; int[][] newMatrix = new int[newSize][newSize];
for (int[] ints : newMatrix) for (int[] ints : newMatrix)
Arrays.fill(ints, NO_EDGE); Arrays.fill(ints, NO_EDGE);
for (int i = 0; i < oldSize; i++) for (int i = 0; i < oldSize; i++)
System.arraycopy(matrix[i], 0, newMatrix[i], 0, oldSize); System.arraycopy(matrix[i], 0, newMatrix[i], 0, oldSize);
return newMatrix; return newMatrix;
} }
private Map<Integer, V> getInverted() { private Map<Integer, V> getInverted() {
Map<Integer, V> invert = new HashMap<>(map.size() + 1, 1); Map<Integer, V> invert = getDefaultMap();
map.forEach((v, i) -> invert.put(i, v)); map.forEach((v, i) -> invert.put(i, v));
return invert; return invert;
} }
} }

View File

@@ -8,7 +8,7 @@ import java.util.*;
public class MatrixUndGraph<V> extends GraphUndirected<V> { public class MatrixUndGraph<V> extends GraphUndirected<V> {
Map<V, Integer> map = new HashMap<>(); Map<V, Integer> map = getDefaultMap();
private int[][] matrix = new int[0][0]; private int[][] matrix = new int[0][0];
@Override @Override
@@ -73,33 +73,33 @@ public class MatrixUndGraph<V> extends GraphUndirected<V> {
} }
@Override @Override
public Collection<V> getChildren(V vertex) throws NullPointerException, IllegalArgumentException { public Set<V> getChildren(V vertex) throws NullPointerException, IllegalArgumentException {
checkVert(vertex); checkVert(vertex);
Collection<V> collection = new HashSet<>(); V[] inverted = getInverted();
Map<Integer, V> inverted = getInverted(); Set<V> set = getDefaultSet();
int x = map.get(vertex); int x = map.get(vertex);
for (int i = 0; i < matrix.length; i++) for (int i = 0; i < matrix.length; i++)
if (i < x && matrix[x][i] != 0) if (i < x && matrix[x][i] != 0)
collection.add(inverted.get(i)); set.add(inverted[i]);
else if (i > x && matrix[i][x] != 0) else if (i > x && matrix[i][x] != 0)
collection.add(inverted.get(i)); set.add(inverted[i]);
return collection; return set;
} }
@Override @Override
public Collection<V> getAncestors(V vertex) throws NullPointerException, IllegalArgumentException { public Set<V> getAncestors(V vertex) throws NullPointerException, IllegalArgumentException {
return getChildren(vertex); return getChildren(vertex);
} }
@Override @Override
public Collection<Edge<V>> edges() { public Set<Edge<V>> edges() {
Map<Integer, V> inverted = getInverted(); V[] inverted = getInverted();
Collection<Edge<V>> edges = new LinkedList<>(); Set<Edge<V>> edges = getDefaultSet();
for (int i = 0; i < matrix.length; i++) for (int i = 0; i < matrix.length; i++)
for (int j = 0; j < matrix[i].length; j++) for (int j = 0; j < matrix[i].length; j++)
if (matrix[i][j] != NO_EDGE) 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; return edges;
} }
@@ -168,9 +168,10 @@ public class MatrixUndGraph<V> extends GraphUndirected<V> {
return newMatrix; return newMatrix;
} }
private Map<Integer, V> getInverted() { @SuppressWarnings("unchecked")
Map<Integer, V> invert = new HashMap<>(map.size() + 1, 1); private V[] getInverted() {
map.forEach((v, i) -> invert.put(i, v)); V[] invert = (V[]) new Object[map.size()];
map.forEach((v, i) -> invert[i] = v);
return invert; return invert;
} }
} }

View File

@@ -1,18 +1,18 @@
package berack96.lib.graph.models; package berack96.lib.graph.models;
/** /**
* Support class used for saving a Graph in a file. * Support class used for saving a Graph in a file.
* *
* @author Berack96 * @author Berack96
*/ */
public class EdgeSaveStructure { public class EdgeSaveStructure {
protected EdgeSaveStructure(String s, String d, int w) { protected EdgeSaveStructure(String s, String d, int w) {
this.src = s; this.src = s;
this.dest = d; this.dest = d;
this.weight = w; this.weight = w;
} }
public String src; public String src;
public String dest; public String dest;
public int weight; public int weight;
} }

View File

@@ -1,105 +1,105 @@
package berack96.lib.graph.models; package berack96.lib.graph.models;
import berack96.lib.graph.Edge; import berack96.lib.graph.Edge;
import berack96.lib.graph.Graph; import berack96.lib.graph.Graph;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
import com.google.gson.InstanceCreator; import com.google.gson.InstanceCreator;
import com.google.gson.JsonSyntaxException; import com.google.gson.JsonSyntaxException;
import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonReader;
import java.io.*; import java.io.*;
/** /**
* Support class used for saving a Graph in a file. * Support class used for saving a Graph in a file.
* *
* @author Berack96 * @author Berack96
*/ */
public class GraphSaveStructure<V> { public class GraphSaveStructure<V> {
final static public Gson gson = new Gson(); final static public Gson gson = new Gson();
public String[] vertices; public String[] vertices;
public EdgeSaveStructure[] edges; public EdgeSaveStructure[] edges;
//public MarkSaveStructure[] marks; //public MarkSaveStructure[] marks;
/** /**
* Load the graph saved in this class in an instance of a graph passed. * Load the graph saved in this class in an instance of a graph passed.
* Before loading the graph, it is emptied. * Before loading the graph, it is emptied.
* *
* @param graph the graph where insert the data * @param graph the graph where insert the data
* @param fileName the file path and name * @param fileName the file path and name
* @param classV the class of the vertices * @param classV the class of the vertices
* @throws FileNotFoundException in the case the file is not found * @throws FileNotFoundException in the case the file is not found
* @throws NullPointerException in the case the graph is null * @throws NullPointerException in the case the graph is null
*/ */
public final void load(@SuppressWarnings("ConstantConditions") Graph<V> graph, String fileName, Class<V> classV) throws FileNotFoundException, NullPointerException { public final void load(Graph<V> graph, String fileName, Class<V> classV) throws FileNotFoundException, NullPointerException {
//this way i use this class for the load //this way i use this class for the load
InstanceCreator<GraphSaveStructure<V>> creator = type -> this; InstanceCreator<GraphSaveStructure<V>> creator = type -> this;
Gson gson = new GsonBuilder().registerTypeAdapter(this.getClass(), creator).create(); Gson gson = new GsonBuilder().registerTypeAdapter(this.getClass(), creator).create();
JsonReader reader = new JsonReader(new FileReader(fileName)); JsonReader reader = new JsonReader(new FileReader(fileName));
gson.fromJson(reader, GraphSaveStructure.class); gson.fromJson(reader, GraphSaveStructure.class);
loadGraph(graph, classV); loadGraph(graph, classV);
} }
/** /**
* This method can be used by sub-classes for saving other stuff from the graph * This method can be used by sub-classes for saving other stuff from the graph
* *
* @param graph the graph to load with * @param graph the graph to load with
* @param classV the class used for the Vertex * @param classV the class used for the Vertex
* @throws NullPointerException if the graph is null * @throws NullPointerException if the graph is null
* @throws JsonSyntaxException if the file is malformed or corrupted * @throws JsonSyntaxException if the file is malformed or corrupted
*/ */
protected void loadGraph(Graph<V> graph, Class<V> classV) throws NullPointerException, JsonSyntaxException { protected void loadGraph(Graph<V> graph, Class<V> classV) throws NullPointerException, JsonSyntaxException {
graph.removeAll(); graph.removeAll();
for (String str : vertices) for (String str : vertices)
graph.add(gson.fromJson(str, classV)); graph.add(gson.fromJson(str, classV));
for (EdgeSaveStructure edge : edges) for (EdgeSaveStructure edge : edges)
graph.addEdge(gson.fromJson(edge.src, classV), gson.fromJson(edge.dest, classV), edge.weight); 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.<br> * Save the Graph passed as input to a file inserted as parameter.<br>
* The resulting file is a Json string representing all the graph.<br> * The resulting file is a Json string representing all the graph.<br>
* If the directory for getting through the file do not exist,<br> * If the directory for getting through the file do not exist,<br>
* then it is created.<br> * then it is created.<br>
* Marks are not included.<br> * Marks are not included.<br>
* The additional parameter is used if you want to save other as well as the graph. * The additional parameter is used if you want to save other as well as the graph.
* *
* @param graph the graph to save * @param graph the graph to save
* @param file the name of the file * @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. * @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<V> graph, String file) throws IOException { public final void save(Graph<V> graph, String file) throws IOException {
saveGraph(graph); saveGraph(graph);
int slash = file.lastIndexOf("\\"); int slash = file.lastIndexOf("\\");
if (slash == -1) if (slash == -1)
slash = file.lastIndexOf("/"); slash = file.lastIndexOf("/");
if (slash != -1) { if (slash != -1) {
String dir = file.substring(0, slash); String dir = file.substring(0, slash);
File fDir = new File(dir); File fDir = new File(dir);
//noinspection ResultOfMethodCallIgnored //noinspection ResultOfMethodCallIgnored
fDir.mkdirs(); fDir.mkdirs();
} }
FileWriter writer = new FileWriter(file); FileWriter writer = new FileWriter(file);
gson.toJson(this, writer); gson.toJson(this, writer);
writer.close(); writer.close();
} }
/** /**
* This method can be used by sub-classes for saving other stuff from the graph * This method can be used by sub-classes for saving other stuff from the graph
* *
* @param graph the graph to save * @param graph the graph to save
*/ */
protected void saveGraph(Graph<V> graph) { protected void saveGraph(Graph<V> graph) {
this.vertices = new String[graph.size()]; this.vertices = new String[graph.size()];
int i = 0; int i = 0;
for (Object o : graph.vertices()) for (Object o : graph.vertices())
this.vertices[i++] = gson.toJson(o); this.vertices[i++] = gson.toJson(o);
this.edges = new EdgeSaveStructure[graph.numberOfEdges()]; this.edges = new EdgeSaveStructure[graph.numberOfEdges()];
i = 0; i = 0;
for (Edge<V> edge : graph.edges()) for (Edge<V> edge : graph.edges())
this.edges[i++] = new EdgeSaveStructure(gson.toJson(edge.getSource()), gson.toJson(edge.getDestination()), edge.getWeight()); this.edges[i++] = new EdgeSaveStructure(gson.toJson(edge.getSource()), gson.toJson(edge.getDestination()), edge.getWeight());
} }
} }

View File

@@ -1,17 +1,17 @@
package berack96.lib.graph.models; package berack96.lib.graph.models;
/** /**
* Support class used for saving a Graph in a file. * Support class used for saving a Graph in a file.
* *
* @author Berack96 * @author Berack96
* *
*/ */
public class MarkSaveStructure { public class MarkSaveStructure {
protected MarkSaveStructure(String v, Object m) { protected MarkSaveStructure(String v, Object m) {
this.vert = v; this.vert = v;
this.mark = m; this.mark = m;
} }
public String vert; public String vert;
public Object mark; public Object mark;
} }

View File

@@ -1,19 +1,20 @@
package berack96.lib.graph.struct; package berack96.lib.graph.struct;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function; import java.util.function.Function;
import berack96.lib.graph.Graph;
/** /**
* Simple implementation of the {@link UnionFind} interface with priority to the find function. * Simple implementation of the {@link UnionFind} interface with priority to the find function.
* *
* @param <X> the elements to search and merge * @param <X> the elements to search and merge
*/ */
public class QuickFind<X> implements UnionFind<X> { public class QuickFind<X> implements UnionFind<X> {
Map<X, Collection<X>> struct = new HashMap<>(); Map<X, Collection<X>> struct = Graph.getDefaultMap();
@Override @Override
public int size() { public int size() {
@@ -22,7 +23,7 @@ public class QuickFind<X> implements UnionFind<X> {
@Override @Override
public void makeSetAll(Collection<X> elements) throws NullPointerException { public void makeSetAll(Collection<X> elements) throws NullPointerException {
Map<X, Collection<X>> temp = new HashMap<>(elements.size() + 1, 1); Map<X, Collection<X>> temp = Graph.getDefaultMap();
for (X elem : elements) for (X elem : elements)
temp.computeIfAbsent(elem, new AddElement()); temp.computeIfAbsent(elem, new AddElement());
struct.putAll(temp); struct.putAll(temp);
@@ -65,10 +66,10 @@ public class QuickFind<X> implements UnionFind<X> {
/** /**
* Stupid class for implementing the adding of a new element * Stupid class for implementing the adding of a new element
*/ */
private class AddElement implements Function<X, Collection<X>> { private class AddElement implements Function<X, Set<X>> {
@Override @Override
public Collection<X> apply(X x) { public Set<X> apply(X x) {
Collection<X> coll = new HashSet<>(); Set<X> coll = Graph.getDefaultSet();
coll.add(x); coll.add(x);
return coll; return coll;
} }

View File

@@ -74,13 +74,13 @@ public class GraphInfo<V> extends JPanel {
components.add(vNumber); components.add(vNumber);
components.add(new JLabel("Edge Number: ")); components.add(new JLabel("Edge Number: "));
components.add(eNumber); components.add(eNumber);
components.add(new JLabel("Is Cyclic: ")); //components.add(new JLabel("Is Cyclic: "));
//components.add(gCyclic); //components.add(gCyclic);
JPanel panelInfo = new JPanel(); JPanel panelInfo = new JPanel();
panelInfo.setOpaque(false); panelInfo.setOpaque(false);
panelInfo.setBorder(BorderFactory.createLineBorder(Color.RED)); panelInfo.setBorder(BorderFactory.createLineBorder(Color.RED));
panelInfo.setLayout(new GridLayout(components.size()/2, 2, 2*2, 2*2)); panelInfo.setLayout(new GridLayout(components.size()/2, 2));
components.forEach(panelInfo::add); components.forEach(panelInfo::add);
components.clear(); components.clear();
@@ -123,7 +123,7 @@ public class GraphInfo<V> extends JPanel {
JPanel panelVertex = new JPanel(); JPanel panelVertex = new JPanel();
panelVertex.setOpaque(false); panelVertex.setOpaque(false);
panelVertex.setLayout(new GridLayout(components.size()/2, 2, 2*2, 2*2)); panelVertex.setLayout(new GridLayout(components.size()/2, 2));
components.forEach(panelVertex::add); components.forEach(panelVertex::add);
components.clear(); components.clear();
@@ -163,7 +163,7 @@ public class GraphInfo<V> extends JPanel {
JPanel panelSave = new JPanel(); JPanel panelSave = new JPanel();
panelSave.setOpaque(false); panelSave.setOpaque(false);
panelSave.setBorder(BorderFactory.createLineBorder(Color.RED)); panelSave.setBorder(BorderFactory.createLineBorder(Color.RED));
panelSave.setLayout(new GridLayout(components.size()/2, 2, 2*2, 2*2)); panelSave.setLayout(new GridLayout(components.size()/2, 2));
components.forEach(panelSave::add); components.forEach(panelSave::add);
components.clear(); components.clear();
@@ -177,7 +177,6 @@ public class GraphInfo<V> extends JPanel {
this.add(panelVertex); this.add(panelVertex);
this.add(panelErrors); this.add(panelErrors);
this.add(panelSave); this.add(panelSave);
/*this.add(panelSave);*/
modVertex.doClick(); modVertex.doClick();

View File

@@ -1,23 +1,23 @@
package berack96.lib.graph.view; package berack96.lib.graph.view;
import berack96.lib.graph.view.edge.EdgeIntListener; import berack96.lib.graph.view.edge.EdgeIntListener;
import berack96.lib.graph.view.edge.EdgeView; import berack96.lib.graph.view.edge.EdgeView;
import berack96.lib.graph.view.vertex.VertexIntListener; import berack96.lib.graph.view.vertex.VertexIntListener;
import berack96.lib.graph.view.vertex.VertexView; import berack96.lib.graph.view.vertex.VertexView;
import java.awt.*; import java.awt.*;
public class Main { public class Main {
public static void main(String[] args) { public static void main(String[] args) {
GraphPanel<Integer> panel = new GraphPanel<>(new VertexView<>(), new EdgeView<>(), Integer.class); GraphPanel<Integer> panel = new GraphPanel<>(new VertexView<>(), new EdgeView<>(), Integer.class);
GraphWindow<Integer> win = new GraphWindow<>(panel, new VertexIntListener(panel), new EdgeIntListener<>(panel)); GraphWindow<Integer> win = new GraphWindow<>(panel, new VertexIntListener(panel), new EdgeIntListener<>(panel));
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize(); // full screen Dimension dim = Toolkit.getDefaultToolkit().getScreenSize(); // full screen
dim.setSize(dim.width / 2, dim.height / 2); dim.setSize(dim.width / 2, dim.height / 2);
win.setSize(dim); win.setSize(dim);
win.setLocationRelativeTo(null); //centered win.setLocationRelativeTo(null); //centered
win.visitRefresh(500); win.visitRefresh(500);
win.setVisible(true); win.setVisible(true);
} }
} }

View File

@@ -2,7 +2,7 @@ package berack96.lib.graph.visit;
import berack96.lib.graph.Edge; import berack96.lib.graph.Edge;
import java.util.Collection; import java.util.Set;
/** /**
* @param <V> * @param <V>
@@ -10,10 +10,11 @@ import java.util.Collection;
public interface VisitMST<V> extends VisitStrategy<V> { public interface VisitMST<V> extends VisitStrategy<V> {
/** /**
* Return the latest calculated MST. * Return the latest calculated MST.<br>
* https://en.wikipedia.org/wiki/Minimum_spanning_tree
* *
* @return the latest MST * @return the latest MST
* @throws NullPointerException if there is no last calculated MST * @throws NullPointerException if there is no last calculated MST
*/ */
Collection<Edge<V>> getMST(); Set<Edge<V>> getMST();
} }

View File

@@ -1,6 +1,6 @@
package berack96.lib.graph.visit; package berack96.lib.graph.visit;
import java.util.Collection; import java.util.Set;
/** /**
* Interface that is helpful for implements visit that needs to retrieve the SCC * Interface that is helpful for implements visit that needs to retrieve the SCC
@@ -16,5 +16,5 @@ public interface VisitSCC<V> extends VisitStrategy<V> {
* @return the latest SCC * @return the latest SCC
* @throws NullPointerException if there is no last calculated SCC * @throws NullPointerException if there is no last calculated SCC
*/ */
Collection<Collection<V>> getSCC(); Set<Set<V>> getSCC();
} }

View File

@@ -1,44 +1,44 @@
package berack96.lib.graph.visit; package berack96.lib.graph.visit;
import berack96.lib.graph.Graph; import berack96.lib.graph.Graph;
import berack96.lib.graph.GraphDirected; import berack96.lib.graph.GraphDirected;
import berack96.lib.graph.visit.impl.VisitInfo; import berack96.lib.graph.visit.impl.VisitInfo;
import java.util.function.Consumer; import java.util.function.Consumer;
/** /**
* This class is used for define some strategy for the visit of a graph. * This class is used for define some strategy for the visit of a graph.
* *
* @param <V> The Object that represent a vertex * @param <V> The Object that represent a vertex
* @author Berack96 * @author Berack96
*/ */
public interface VisitStrategy<V> { public interface VisitStrategy<V> {
/** /**
* With this the graph will be visited accordingly to the strategy of the visit.<br> * With this the graph will be visited accordingly to the strategy of the visit.<br>
* Some strategy can accept a source vertex null, because they visit all the graph anyway.<br> * Some strategy can accept a source vertex null, because they visit all the graph anyway.<br>
* If you want to stop the visit of the graph, you just have to throw any exception in the visit function, but be sure to catch it * If you want to stop the visit of the graph, you just have to throw any exception in the visit function, but be sure to catch it
* *
* @param graph the graph to visit * @param graph the graph to visit
* @param source the vertex where the visit starts * @param source the vertex where the visit starts
* @param visit the function to apply at each vertex when they are visited * @param visit the function to apply at each vertex when they are visited
* @return an info of the view * @return an info of the view
* @throws NullPointerException if the graph is null * @throws NullPointerException if the graph is null
* @throws UnsupportedOperationException in the case that the visit algorithm cannot be applied to the graph * @throws UnsupportedOperationException in the case that the visit algorithm cannot be applied to the graph
*/ */
VisitInfo<V> visit(Graph<V> graph, V source, Consumer<V> visit) throws NullPointerException, UnsupportedOperationException; VisitInfo<V> visit(Graph<V> graph, V source, Consumer<V> visit) throws NullPointerException, UnsupportedOperationException;
/** /**
* Method used for checking if the graph is Directed.<br> * Method used for checking if the graph is Directed.<br>
* It's useful when the algorithm can only be applied to Directed graph. * It's useful when the algorithm can only be applied to Directed graph.
* *
* @param graph the instance of the graph to check * @param graph the instance of the graph to check
* @return the instance of the graph casted to a {@link GraphDirected} * @return the instance of the graph casted to a {@link GraphDirected}
* @throws UnsupportedOperationException in the case it's not a directed graph * @throws UnsupportedOperationException in the case it's not a directed graph
*/ */
default GraphDirected<V> checkDirected(Graph<V> graph) { default GraphDirected<V> checkDirected(Graph<V> graph) {
if (graph instanceof GraphDirected) if (graph instanceof GraphDirected)
return (GraphDirected<V>) graph; return (GraphDirected<V>) graph;
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
} }

View File

@@ -32,8 +32,8 @@ public class Dijkstra<V> implements VisitDistance<V> {
public VisitInfo<V> visit(Graph<V> graph, V source, Consumer<V> visit) throws NullPointerException, IllegalArgumentException { public VisitInfo<V> visit(Graph<V> graph, V source, Consumer<V> visit) throws NullPointerException, IllegalArgumentException {
VisitInfo<V> info = new VisitInfo<>(source); VisitInfo<V> info = new VisitInfo<>(source);
Queue<QueueEntry> queue = new PriorityQueue<>(); Queue<QueueEntry> queue = new PriorityQueue<>();
Map<V, Integer> dist = new HashMap<>(); Map<V, Integer> dist = Graph.getDefaultMap();
Map<V, V> prev = new HashMap<>(); Map<V, V> prev = Graph.getDefaultMap();
this.source = source; this.source = source;
dist.put(source, 0); // Initialization dist.put(source, 0); // Initialization
@@ -63,7 +63,7 @@ public class Dijkstra<V> implements VisitDistance<V> {
} }
/* Cleaning up the results */ /* Cleaning up the results */
distance = new HashMap<>(); distance = Graph.getDefaultMap();
for (V vertex : prev.keySet()) { for (V vertex : prev.keySet()) {
List<Edge<V>> path = new LinkedList<>(); List<Edge<V>> path = new LinkedList<>();
V child = vertex; V child = vertex;

View File

@@ -17,10 +17,10 @@ import java.util.function.Consumer;
* @param <V> The vertex of the graph * @param <V> The vertex of the graph
*/ */
public class Kruskal<V> implements VisitMST<V> { public class Kruskal<V> implements VisitMST<V> {
private Collection<Edge<V>> mst; private Set<Edge<V>> mst;
@Override @Override
public Collection<Edge<V>> getMST() { public Set<Edge<V>> getMST() {
return mst; return mst;
} }
@@ -32,7 +32,7 @@ public class Kruskal<V> implements VisitMST<V> {
List<Edge<V>> edges = new ArrayList<>(graph.edges()); List<Edge<V>> edges = new ArrayList<>(graph.edges());
Collections.sort(edges); Collections.sort(edges);
mst = new HashSet<>(graph.size(), 1); mst = Graph.getDefaultSet();
Iterator<Edge<V>> iter = edges.iterator(); Iterator<Edge<V>> iter = edges.iterator();
while (iter.hasNext() && sets.size() > 1) { while (iter.hasNext() && sets.size() > 1) {
Edge<V> edge = iter.next(); Edge<V> edge = iter.next();

View File

@@ -5,8 +5,7 @@ import berack96.lib.graph.Graph;
import berack96.lib.graph.GraphUndirected; import berack96.lib.graph.GraphUndirected;
import berack96.lib.graph.visit.VisitMST; import berack96.lib.graph.visit.VisitMST;
import java.util.Collection; import java.util.Set;
import java.util.LinkedList;
import java.util.function.Consumer; import java.util.function.Consumer;
/** /**
@@ -17,17 +16,17 @@ import java.util.function.Consumer;
*/ */
public class Prim<V> implements VisitMST<V> { public class Prim<V> implements VisitMST<V> {
private Collection<Edge<V>> mst; private Set<Edge<V>> mst;
@Override @Override
public Collection<Edge<V>> getMST() { public Set<Edge<V>> getMST() {
return mst; return mst;
} }
@Override @Override
public VisitInfo<V> visit(Graph<V> graph, V source, Consumer<V> visit) throws NullPointerException, UnsupportedOperationException { public VisitInfo<V> visit(Graph<V> graph, V source, Consumer<V> visit) throws NullPointerException, UnsupportedOperationException {
mst = new LinkedList<>(); mst = Graph.getDefaultSet();
Collection<V> vertices = graph.vertices(); Set<V> vertices = graph.vertices();
if (source == null) if (source == null)
source = vertices.iterator().next(); source = vertices.iterator().next();

View File

@@ -15,7 +15,7 @@ import java.util.function.Consumer;
*/ */
public class Tarjan<V> implements VisitSCC<V>, VisitTopological<V> { public class Tarjan<V> implements VisitSCC<V>, VisitTopological<V> {
private Collection<Collection<V>> SCC = null; private Set<Set<V>> SCC = null;
private List<V> topologicalSort = null; private List<V> topologicalSort = null;
private Map<V, Integer> indices = null; private Map<V, Integer> indices = null;
@@ -24,7 +24,7 @@ public class Tarjan<V> implements VisitSCC<V>, VisitTopological<V> {
private VisitInfo<V> info = null; private VisitInfo<V> info = null;
@Override @Override
public Collection<Collection<V>> getSCC() { public Set<Set<V>> getSCC() {
return SCC; return SCC;
} }
@@ -44,12 +44,12 @@ public class Tarjan<V> implements VisitSCC<V>, VisitTopological<V> {
*/ */
@Override @Override
public VisitInfo<V> visit(Graph<V> graph, V source, Consumer<V> visit) throws NullPointerException, IllegalArgumentException { public VisitInfo<V> visit(Graph<V> graph, V source, Consumer<V> visit) throws NullPointerException, IllegalArgumentException {
SCC = new HashSet<>(); SCC = Graph.getDefaultSet();
topologicalSort = new ArrayList<>(graph.size()); topologicalSort = new ArrayList<>(graph.size());
info = null; info = null;
indices = new HashMap<>(); indices = Graph.getDefaultMap();
lowLink = new HashMap<>(); lowLink = Graph.getDefaultMap();
stack = new Stack<>(); stack = new Stack<>();
int index = 0; int index = 0;
@@ -89,7 +89,7 @@ public class Tarjan<V> implements VisitSCC<V>, VisitTopological<V> {
// If v is a root node, pop the stack and generate an SCC // If v is a root node, pop the stack and generate an SCC
if (lowLink.get(vertex).equals(indices.get(vertex))) { if (lowLink.get(vertex).equals(indices.get(vertex))) {
Set<V> newComponent = new HashSet<>(); Set<V> newComponent = Graph.getDefaultSet();
V temp; V temp;
do { do {
temp = stack.pop(); temp = stack.pop();

View File

@@ -23,6 +23,7 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.PrintStream; import java.io.PrintStream;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.net.URISyntaxException;
import java.util.*; import java.util.*;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Stream; import java.util.stream.Stream;
@@ -1531,7 +1532,7 @@ public class TestGraph {
shouldContain(sub.edges(), shouldContain(sub.edges(),
new Edge<>("4", "6", 6), new Edge<>("4", "6", 6),
new Edge<>("6", "2", 2)); new Edge<>("6", "2", 2));
sub = graph.subGraph("blue", "circle"); sub = graph.subGraph("blue", "circle");
shouldContain(sub.vertices(), "1", "2", "3", "4", "5", "6"); shouldContain(sub.vertices(), "1", "2", "3", "4", "5", "6");
shouldContain(sub.edges(), shouldContain(sub.edges(),
@@ -1543,11 +1544,27 @@ public class TestGraph {
new Edge<>("5", "4", 5), new Edge<>("5", "4", 5),
new Edge<>("6", "2", 2)); new Edge<>("6", "2", 2));
sub = graph.subGraph("even", "even");
shouldContain(sub.vertices(), "2", "4", "6");
shouldContain(sub.edges(),
new Edge<>("4", "6", 6),
new Edge<>("6", "2", 2));
sub = graph.subGraph("even", null, "even");
shouldContain(sub.vertices(), "2", "4", "6");
shouldContain(sub.edges(),
new Edge<>("4", "6", 6),
new Edge<>("6", "2", 2));
sub = graph.subGraph((Object) null);
shouldContain(sub.vertices(), "7", "8");
shouldContain(sub.edges(), new Edge<>("8", "7", 9));
sub = graph.subGraph(); sub = graph.subGraph();
shouldContain(sub.vertices(), "7", "8"); shouldContain(sub.vertices(), "7", "8");
shouldContain(sub.edges(), new Edge<>("8", "7", 9)); shouldContain(sub.edges(), new Edge<>("8", "7", 9));
sub = graph.subGraph(null); sub = graph.subGraph((Object[]) null);
shouldContain(sub.vertices(), "7", "8"); shouldContain(sub.vertices(), "7", "8");
shouldContain(sub.edges(), new Edge<>("8", "7", 9)); shouldContain(sub.edges(), new Edge<>("8", "7", 9));
} }
@@ -1672,7 +1689,7 @@ public class TestGraph {
//TODO tests for GraphUndirected save/load //TODO tests for GraphUndirected save/load
@ParameterizedTest @ParameterizedTest
@MethodSource("getGraphsDir") @MethodSource("getGraphsDir")
public void saveLoadDir(final GraphDirected<String> graph) { public void saveLoadDir(final GraphDirected<String> graph) throws URISyntaxException {
/* /*
* This graph should be like this * This graph should be like this
* *
@@ -1682,8 +1699,7 @@ public class TestGraph {
* v v * v v
* 3 <- 5 -> 4 8 * 3 <- 5 -> 4 8
*/ */
String fileName = ClassLoader.getSystemResource("").getPath() + "resources/test.json";
String fileName = "test/resources/test.json";
Set<String> vertices = Set.of("1", "2", "3", "4", "5", "6", "7", "8"); Set<String> vertices = Set.of("1", "2", "3", "4", "5", "6", "7", "8");
Set<Edge<String>> edges = new HashSet<>(); Set<Edge<String>> edges = new HashSet<>();
Map<String, Set<Object>> marks = new HashMap<>(); Map<String, Set<Object>> marks = new HashMap<>();

View File

@@ -0,0 +1 @@
{"vertices":["\"6\"","\"5\"","\"4\"","\"3\"","\"2\"","\"1\"","\"8\"","\"7\""],"edges":[{"src":"\"4\"","dest":"\"6\"","weight":6},{"src":"\"2\"","dest":"\"5\"","weight":4},{"src":"\"5\"","dest":"\"4\"","weight":5},{"src":"\"5\"","dest":"\"3\"","weight":2},{"src":"\"1\"","dest":"\"3\"","weight":1},{"src":"\"6\"","dest":"\"2\"","weight":2},{"src":"\"1\"","dest":"\"2\"","weight":1},{"src":"\"8\"","dest":"\"7\"","weight":9}]}

View File

@@ -1,54 +0,0 @@
{
"vertices": [
"\"6\"",
"\"5\"",
"\"4\"",
"\"3\"",
"\"2\"",
"\"1\"",
"\"8\"",
"\"7\""
],
"edges": [
{
"src": "\"4\"",
"dest": "\"6\"",
"weight": 6
},
{
"src": "\"2\"",
"dest": "\"5\"",
"weight": 4
},
{
"src": "\"5\"",
"dest": "\"4\"",
"weight": 5
},
{
"src": "\"5\"",
"dest": "\"3\"",
"weight": 2
},
{
"src": "\"1\"",
"dest": "\"3\"",
"weight": 1
},
{
"src": "\"6\"",
"dest": "\"2\"",
"weight": 2
},
{
"src": "\"1\"",
"dest": "\"2\"",
"weight": 1
},
{
"src": "\"8\"",
"dest": "\"7\"",
"weight": 9
}
]
}