1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
| /** Represente un graphe sur lequel nous pourrons verifier si il posséde des cycles
*/
private static class Graph
{
// Liste des points du graphe
private List<GraphPoint> points = new ArrayList<GraphPoint>();
// Liste de tout les segments
private List<GraphSegment> segments = new ArrayList<GraphSegment>();
// Liste résultat donnant les segments a supprimer afin d'eviter tout cycle */
private Set<GraphSegment> segmentsToRemove = null;
/** Construction du graphe a partir d'une liste de segments
*/
public Graph( GraphSegment[] s )
{
for(int i = 0 ; i < s.length ; i++ )
{
segments.add( s[i] );
if( ! points.contains( s[i].getSourcePoint() ) ) points.add( s[i].getSourcePoint() );
if( ! points.contains( s[i].getDestPoint() ) ) points.add( s[i].getDestPoint() );
}
}
/** Indique si des cycles sont présents dans le graphe
*/
public boolean hasCycles()
{
/** First all, reset all attributes */
this.initSearch();
return !this.segmentsToRemove.isEmpty();
}
/** récupere la liste des segments à supprimer afin de ne plus avoir de cycles dans le graphe
*/
public GraphSegment[] getSegmentsToRemove()
{ if( this.segmentsToRemove == null ) this.hasCycles();
return this.segmentsToRemove.toArray( new GraphSegment[]{} );
}
/** lance searchCycle sur le 1er point. Une fois sa recherche terminé, relancer pour le prochain point non encore visité, etc...
*/
private void initSearch()
{
for(int i = 0 ; i < points.size() ; i ++)
points.get(i).setAsVisited(false);
if( this.segmentsToRemove != null )
{
this.segmentsToRemove.clear();
this.segmentsToRemove = null;
}
this.segmentsToRemove = new HashSet<GraphSegment>();
for(int i = 0 ; i < this.points.size() ; i++ )
{
if( ! this.points.get(i).isVisited() )
this.searchCycle( this.points.get(i) , new HashSet<GraphPoint>() );
}
}
/** Parcours le graphe à partir d'un point donné
* Si un cycle est determiné, on met a jour la liste des segments a supprimer
* @param point Point a partir duquel on parcours le graph
* @param ctx Contexte du chemin déja parcourus (points sur lesquels on est déja passé)
*
*/
private void searchCycle( GraphPoint point , Set<GraphPoint> ctx )
{
// On sera passé au moins une fois sur ce point
point.setAsVisited(true);
// Rajoute le point dans le contexte
ctx.add( point );
// Parcours tout les successeurs
Iterator<GraphSegment> i = point.path();
while( i.hasNext() )
{
GraphSegment path = i.next();
// Si le chemin est déja supprimé, ne plus le parcourir
if( this.segmentsToRemove.contains( path ) ) continue;
// Récupere le successeur
GraphPoint successor = path.getDestPoint();
if( ctx.contains(successor) )
{
this.segmentsToRemove.add( path );
continue;
}
// Récursion
this.searchCycle( successor , ctx );
}
// Restauration du contexte
ctx.remove( point );
}
} |
Partager