312 lines
7.7 KiB
Java
312 lines
7.7 KiB
Java
package network.network;
|
|
|
|
import network.Graph;
|
|
|
|
import java.util.HashMap;
|
|
import java.util.Iterator;
|
|
import java.util.LinkedList;
|
|
import java.util.Map;
|
|
import java.util.Queue;
|
|
import java.util.Set;
|
|
import java.util.Stack;
|
|
import java.util.TreeMap;
|
|
import java.util.TreeSet;
|
|
|
|
public class Network<Vertex extends Comparable<? super Vertex>> implements Graph<Vertex, Double>{
|
|
|
|
protected TreeMap<Vertex, TreeMap<Vertex, Double>> adjacencyMap;
|
|
|
|
public Network() {
|
|
this.adjacencyMap = new TreeMap<Vertex, TreeMap<Vertex, Double>>();
|
|
}
|
|
|
|
public Network(Network<Vertex> network) {
|
|
this.adjacencyMap = new TreeMap<Vertex, TreeMap<Vertex, Double>>(network.adjacencyMap);
|
|
}
|
|
|
|
@Override
|
|
public boolean equals(Object object) {
|
|
if (object == null) return false;
|
|
if (object == this) return true;
|
|
if (!(object instanceof Network)) return false;
|
|
|
|
Network<?> network = (Network<?>) object;
|
|
|
|
return adjacencyMap.equals(network.adjacencyMap);
|
|
}
|
|
|
|
@Override
|
|
public boolean containsVertex(Vertex vertex) {
|
|
return adjacencyMap.containsKey(vertex);
|
|
}
|
|
|
|
@Override
|
|
public boolean addVertex(Vertex vertex) {
|
|
// Null Check
|
|
if (vertex == null) throw new NullPointerException();
|
|
// Se l'elemento è già presente
|
|
if (containsVertex(vertex)) return false;
|
|
// Inserimento
|
|
adjacencyMap.put(vertex, new TreeMap<Vertex, Double>());
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public boolean removeVertex(Vertex vertex) {
|
|
// Null check
|
|
if (vertex == null) throw new NullPointerException();
|
|
// Se l'elemento non è presente
|
|
if (!containsVertex(vertex)) return false;
|
|
// Rimozione del vertice dalle liste di adiacenza
|
|
for (Vertex v : adjacencyMap.keySet()) {
|
|
adjacencyMap.get(v).remove(vertex);
|
|
}
|
|
// Rimozione del vertice dalle chiavi
|
|
adjacencyMap.remove(vertex);
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* Restituisce il numero di archi presenti all'interno del grafo
|
|
*/
|
|
@Override
|
|
public int edgeSize() {
|
|
// Variabile contatore
|
|
int edges = 0;
|
|
// Conto degli archi
|
|
for (Vertex v : adjacencyMap.keySet()) {
|
|
edges += adjacencyMap.get(v).size();
|
|
}
|
|
return edges;
|
|
}
|
|
|
|
@Override
|
|
public Double getEdgeWheight(Vertex v1, Vertex v2) {
|
|
// Null check
|
|
if (v1 == null || v2 == null) throw new NullPointerException();
|
|
// Verifichiamo se ambedue sono presenti nel grafo, se non ci sono allora return null.
|
|
if (!(containsVertex(v1) && containsVertex(v2))) return null;
|
|
// Otteniamo la lista di adiacenza
|
|
Map<Vertex, Double> tmp = adjacencyMap.get(v1);
|
|
// Se il vertex2 non presenta il vertice2 allora non esiste il peso
|
|
if (!tmp.containsKey(v2)) return null;
|
|
return tmp.get(v2);
|
|
}
|
|
|
|
@Override
|
|
public boolean containsEdge(Vertex v1, Vertex v2) {
|
|
// Null check
|
|
if (v1 == null || v2 == null) throw new NullPointerException();
|
|
// Verifichiamo che ambedue siano nel grafico
|
|
if (!(containsVertex(v1) && containsVertex(v2))) return false;
|
|
// Otteniamo la lista di adiacenza
|
|
Map<Vertex, Double> tmp = adjacencyMap.get(v1);
|
|
return tmp.containsKey(v2);
|
|
}
|
|
|
|
@Override
|
|
public boolean addEdge(Vertex v1, Vertex v2, Double weight) {
|
|
// Null check
|
|
if (v1 == null || v2 == null || weight == null) throw new NullPointerException();
|
|
// Verifichiamo che ambedue siano nel grafico
|
|
if (!(containsVertex(v1) && containsVertex(v2))) return false;
|
|
// Verifichiamo che non esista l'arco. Se esiste allora non fa nulla. Se non esiste lo aggiunge.
|
|
if (containsEdge(v1, v2)) return false;
|
|
// Aggiunta dell'edge
|
|
Map<Vertex, Double> tmp = adjacencyMap.get(v1);
|
|
tmp.put(v2, weight);
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public boolean removeEdge(Vertex v1, Vertex v2) {
|
|
// Null check
|
|
if (v1 == null || v2 == null) throw new NullPointerException();
|
|
// Verifichiamo che ambedue siano nel grafico
|
|
if (!(containsVertex(v1) && containsVertex(v2))) return false;
|
|
// Verifichiamo se l'arco esiste oppure no.
|
|
if (!containsEdge(v1, v2)) return false;
|
|
// Rimozione dell'edge
|
|
Map<Vertex, Double> tmp = adjacencyMap.get(v1);
|
|
tmp.remove(v2);
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public boolean isEmpty() {
|
|
return adjacencyMap.isEmpty();
|
|
}
|
|
|
|
@Override
|
|
public int size() {
|
|
return adjacencyMap.keySet().size();
|
|
}
|
|
|
|
@Override
|
|
public Set<Vertex> neighbors(Vertex v) {
|
|
// Null check
|
|
if (v == null) throw new NullPointerException();
|
|
// Presenza del vertice nel grafo
|
|
if (!containsVertex(v)) return null;
|
|
// Se il vertice è presente, allora restituisco il tutto
|
|
return new TreeSet<Vertex>(adjacencyMap.get(v).keySet());
|
|
}
|
|
|
|
@Override
|
|
public Iterator<Vertex> iterator() {
|
|
return new NetworkIterator();
|
|
}
|
|
|
|
protected class NetworkIterator implements Iterator<Vertex> {
|
|
|
|
// Variabili
|
|
protected Iterator<Vertex> iterator;
|
|
protected Vertex currentVertex;
|
|
|
|
// Costruttore
|
|
public NetworkIterator() {
|
|
this.iterator = adjacencyMap.keySet().iterator();
|
|
}
|
|
|
|
// hasNext
|
|
public boolean hasNext() {
|
|
return this.iterator.hasNext();
|
|
}
|
|
|
|
// next
|
|
public Vertex next() {
|
|
this.currentVertex = iterator.next();
|
|
return this.currentVertex;
|
|
}
|
|
|
|
// remove
|
|
public void remove() {
|
|
throw new UnsupportedOperationException();
|
|
}
|
|
|
|
}
|
|
|
|
@Override
|
|
public Iterator<Vertex> breadthFirstIterator(Vertex vertex) {
|
|
if (!this.adjacencyMap.containsKey(vertex)) throw new IllegalArgumentException();
|
|
return new BreadthFirstIterator(vertex);
|
|
}
|
|
|
|
protected class BreadthFirstIterator implements Iterator<Vertex> {
|
|
|
|
// Variabili
|
|
protected Queue<Vertex> queue;
|
|
protected HashMap<Vertex, Boolean> research;
|
|
protected Vertex currentVertex;
|
|
|
|
// Costruttore
|
|
public BreadthFirstIterator(Vertex vertex) {
|
|
this.queue = new LinkedList<Vertex>();
|
|
this.research = new HashMap<Vertex, Boolean>();
|
|
|
|
for (Vertex v : adjacencyMap.keySet()) {
|
|
research.put(v, false);
|
|
}
|
|
|
|
queue.add(vertex);
|
|
research.put(vertex, true);
|
|
}
|
|
|
|
public boolean hasNext() {
|
|
return !(queue.isEmpty());
|
|
}
|
|
|
|
public Vertex next() {
|
|
currentVertex = queue.remove();
|
|
|
|
Set<Vertex> neighborsSet = adjacencyMap.get(currentVertex).keySet();
|
|
|
|
for (Vertex v : neighborsSet) {
|
|
if (research.get(v)) continue;
|
|
research.put(v, true);
|
|
queue.add(v);
|
|
}
|
|
|
|
return currentVertex;
|
|
}
|
|
|
|
public void remove() {
|
|
throw new UnsupportedOperationException();
|
|
}
|
|
|
|
}
|
|
|
|
@Override
|
|
public Iterator<Vertex> depthFisrtIterator(Vertex v) {
|
|
return new DepthFirstIterator(v);
|
|
}
|
|
|
|
protected class DepthFirstIterator implements Iterator<Vertex>{
|
|
|
|
// Variabili
|
|
protected Stack<Vertex> stack = new Stack<Vertex>();
|
|
protected HashMap<Vertex, Boolean> reached;
|
|
Vertex current;
|
|
|
|
// Costruttore
|
|
public DepthFirstIterator(Vertex vertex) {
|
|
this.stack = new Stack<Vertex>();
|
|
this.reached = new HashMap<Vertex, Boolean>();
|
|
|
|
for (Vertex v : adjacencyMap.keySet()) {
|
|
this.reached.put(v, false);
|
|
}
|
|
|
|
this.stack.add(vertex);
|
|
this.reached.put(vertex, true);
|
|
}
|
|
|
|
public boolean hasNext() {
|
|
return !stack.isEmpty();
|
|
}
|
|
|
|
public Vertex next() {
|
|
this.current = this.stack.pop();
|
|
|
|
Set<Vertex> neighborsSet = adjacencyMap.get(this.current).keySet();
|
|
for (Vertex v : neighborsSet) {
|
|
if (this.reached.get(v)) {
|
|
if (this.stack.remove(v)) stack.add(v);
|
|
} else {
|
|
this.stack.add(v);
|
|
this.reached.put(v, true);
|
|
}
|
|
}
|
|
|
|
return current;
|
|
}
|
|
|
|
public void remove() {
|
|
throw new UnsupportedOperationException();
|
|
}
|
|
|
|
}
|
|
|
|
// ESERCIZI
|
|
|
|
/*
|
|
* Un grafo è detto fortementeConnesso quando per ogni vertice
|
|
* si può raggiungere un qualsiasi altro vertice del grafo
|
|
*/
|
|
public boolean isStronglyConnected() {
|
|
for (Vertex SS : adjacencyMap.keySet()) {
|
|
Iterator<Vertex> it = this.breadthFirstIterator(SS);
|
|
int counter = 0;
|
|
while (it.hasNext()) {
|
|
counter++;
|
|
it.next();
|
|
}
|
|
if (counter < adjacencyMap.size()) return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
}
|