2020-09-09 14:43:31 +02:00

261 lines
7.0 KiB
Java
Raw Blame History

package designPattern.grapheSimple;
import designPattern.grapheX.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
/**
* Cette classe a ete necessaire pour gérer les graphes ayant plusieurs arétes entre deux sommets données
* et ayant des arcs dans les deux sens entre deux sommets.
* Ces fonctionnalités n'étaient pas prises en charge par les classes initiales.
* Elle permet egalement de simplifier la comprehension des codes données.
* @author blay
*
*/
public class GrapheSimple<T extends Sommet> extends Graphe<T> {
HashMap<String,T> mesSommets = new HashMap<>();
HashMap<T,HashMap<T,ArrayList<Arc<T>>>> aretes;
public GrapheSimple() {
aretes = new HashMap<>();
}
public T getSommet(String ident){
return mesSommets.get(ident);
}
@Override
public int taille() {
return mesSommets.size();
}
@Override
public Graphe<T> copie() {
//@TODO
return null;
}
//n'ajoute le sommet que s'il n'est pas deja dans le graphe.
@Override
public void ajouterSommet(T s) {
if (existeSommet(s))
return;
mesSommets.put(s.identifiant(), s);
aretes.put(s,new HashMap<T,ArrayList<Arc<T>>>());
}
@Override
public boolean existeArc(Sommet s, Sommet t) {
return aretes.get(s).containsKey(t);
}
//A revoir avec la nouvelle version
//@todo
private boolean existeSommet(T s) {
return aretes.containsKey(s);
}
public List<Arc<T>> arcs(T s, T t) {
return aretes.get(s).get(t);
}
@Override
public void ajouterArc(T s, T t) {
this.ajouterArc(s,t,0);
}
@Override
public void ajouterArc(Arc<T> arc) {
HashMap<T, ArrayList<Arc<T>>> s = aretes.get(arc.origine());
if (s == null){
ajouterSommet(arc.origine());
s=aretes.get(arc.origine());
}
if (aretes.get(arc.destination()) == null)
ajouterSommet(arc.destination());
if (s.get(arc.destination()) == null)
s.put(arc.destination(), new ArrayList<>());
s.get(arc.destination()).add(arc);
}
@Override
public void ajouterArc(T s, T t, int val) {
Arc<T> a = new Arc<>(s,t,val);
this.ajouterArc(a);
}
//Remarque : gestion horrible des exceptions mais on s'adapte à cause de l'héritage qui nous interdit de lever une exception.
@Override
public int valeurArc(T s, T t) {
if (!existeArc(s,t)) throw new Error("Arc inexistant");
return aretes.get(s).get(t).get(0).valeur();
}
//RETIRE TOUS LES ARCS VERS T
@Override
public void enleverArc(Sommet s, Sommet t) {
if (!existeArc(s,t)) return ;
aretes.get(s).remove(t);
}
@Override
public Collection<T> sommets() {
return mesSommets.values();
}
@Override
public Collection<Arc<T>> voisins(Sommet s) {
ArrayList<Arc<T>> voisins = new ArrayList<>();
HashMap<T, ArrayList<Arc<T>>> arcs = aretes.get(s);
if ( arcs != null )
for (ArrayList<Arc<T>> av : arcs.values())
voisins.addAll(av);
return voisins ;
}
@Override
public String toString() {
return "Sommets=" + mesSommets + ";\n arcs="
+ toStringArretes(aretes) + "]";
}
private String toStringArretes(
HashMap<T, HashMap<T, ArrayList<Arc<T>>>> aretes2) {
StringBuilder bld = new StringBuilder();
for ( HashMap<T, ArrayList<Arc<T>>> x : aretes2.values()){
for ( ArrayList<Arc<T>> edges : x.values())
for (Arc<T> a : edges)
bld.append( "\t").append(a).append("\n" );
}
return bld.toString();
}
/**
* @param origine
* @return une liste de chemin
* Cette m<>thode renvoie les chemins les plus longs possibles <20> partir du point d'orgine
*/
public List<Chemin<T>> chemins(T origine){
HashMap<T,ArrayList<Arc<T>>> dejaVu = new HashMap<>();
return chemins(origine,dejaVu);
}
/**
* @param origine
* @param destination
* @return une liste de chemins entre deux Ts
* Cette m<>thode renvoie tous les chemins entre deux Sommets donnes
*/
//Pbme avec la comparaison des chemins... qui considere comme <20>gal deux objets diff<66>rents... cela doit venir de l'h<>ritage...
public List<Chemin<T>> chemins(T origine, T destination){
List<Chemin<T>> chemins = chemins(origine);
List<Chemin<T>> cheminsEntreDeuxSommets = new ArrayList<> ();
for(Chemin<T> c : chemins) {
if (c.atteint(destination)){
Chemin<T> raccourcis = c.extraireChemin(origine, destination);
if (! cheminsEntreDeuxSommets.contains(raccourcis)) {
cheminsEntreDeuxSommets.add(raccourcis);
}
}
}
return cheminsEntreDeuxSommets;
}
private List<Chemin<T>> chemins(T origine, HashMap<T,ArrayList<Arc<T>>> dejaVu){
List<Chemin<T>> chemins = new ArrayList<>();
if (dejaVu.containsKey(origine)){
chemins.add(new Chemin<>(dejaVu.get(origine)));
return chemins;
}
dejaVu.put(origine, new ArrayList<Arc<T>>());
Collection<Arc<T>> voisins = voisins(origine);
HashMap<T,ArrayList<Arc<T>>> dejavVuLocal ;
for (Arc<T> a : voisins) {
T destination = a.destination();
dejavVuLocal= new HashMap<>(dejaVu);
if (nouvelleDestinationOuNouvelArcSansRetour(origine,dejavVuLocal,destination,a)) {
dejavVuLocal.get(origine).add(a);
List<Chemin<T>> cheminsLocaux = chemins(destination,dejavVuLocal);
if (cheminsLocaux.isEmpty()) {
Chemin<T> chemin = new Chemin<>();
chemin.add(a);
chemins.add(chemin);
}
else {
for (Chemin<T> c : cheminsLocaux) {
c.add(0,a);
chemins.add(c);
}
}
}
}
return chemins;
}
//todo : tenir compte de Origine
private boolean nouvelleDestinationOuNouvelArcSansRetour(
T origine, HashMap<T, ArrayList<Arc<T>>> dejaVu, T destination,
Arc<T> a) {
if (! dejaVu.containsKey(destination) )
return true;
return ( (! dejaVu.get(destination).contains(a)) && (! dejaVu.containsKey(a.destination()) ) );
}
public Chemin<T> cheminLePlusCourt(T origine, T destination){
List<Chemin<T>> chemins = this.chemins(origine, destination);
Chemin<T> cheminLePlusCourt = null;
int distanceLaPlusCourte = Integer.MAX_VALUE;
for(Chemin<T> c : chemins) {
if (distanceLaPlusCourte > c.distance()) {
distanceLaPlusCourte = c.distance();
cheminLePlusCourt = c;
}
}
return cheminLePlusCourt;
}
public Set<T> voisinsAuRang(T origine, int rang){
List<Chemin<T>> chemins = chemins(origine);
Set<T> TsVoisinsDejaVu = new TreeSet<>();
Set<T> TsDeBonRang = new TreeSet<>();
for (Chemin<T> c : chemins) {
List<T> sommets = c.sommets();
int i = 0;
for (i = 0; (i <sommets.size() && i < rang); i++)
TsVoisinsDejaVu.add(sommets.get(i));
if ( (i == rang) && (i < sommets.size()) )
TsDeBonRang.add(sommets.get(i));
}
TsDeBonRang.removeAll(TsVoisinsDejaVu);
return TsDeBonRang;
}
}