Refactoring
- changed to maven - modified hashMap and HashSet to Tree - modified files path
This commit is contained in:
5
.gitignore
vendored
5
.gitignore
vendored
@@ -125,8 +125,9 @@ local.properties
|
|||||||
|
|
||||||
|
|
||||||
# mine
|
# mine
|
||||||
|
target/
|
||||||
.idea/*
|
.idea/*
|
||||||
.project
|
.project
|
||||||
*.iml
|
*.iml
|
||||||
.classpath
|
.classpath
|
||||||
/.gradle/
|
/.gradle/
|
||||||
|
|||||||
32
build.gradle
32
build.gradle
@@ -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
80
pom.xml
Normal 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>
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
18
src/main/java/berack96/lib/graph/ObjectsComparator.java
Normal file
18
src/main/java/berack96/lib/graph/ObjectsComparator.java
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
@@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
@@ -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();
|
||||||
|
|
||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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();
|
||||||
}
|
}
|
||||||
@@ -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();
|
||||||
}
|
}
|
||||||
@@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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;
|
||||||
@@ -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();
|
||||||
@@ -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();
|
||||||
@@ -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();
|
||||||
@@ -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<>();
|
||||||
1
src/test/java/resources/test.json
Normal file
1
src/test/java/resources/test.json
Normal 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}]}
|
||||||
@@ -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
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user