Algorithme de Dijkstra liste Adjacente java

Fermé
Gata - 16 nov. 2009 à 23:17
 Gata - 23 nov. 2009 à 19:27
Bonjour,
Je souhaite implémenter l'algorithme de Dijkstra à l'aide de listes Adjacentes.
Celui ci est expliquer partout avec des tableaux de matrices. Je suis un peu perdu .
Pouvez vous m'aidez ?

Merci d'avance :)
A voir également:

3 réponses

Pacorabanix Messages postés 3248 Date d'inscription jeudi 23 août 2007 Statut Membre Dernière intervention 19 mai 2013 661
16 nov. 2009 à 23:35
l'idée :

ton graphe est composé de "points", à la manière d'un ensemble en maths (une structure de donnée souvent appelée Set plus ou moins). Chaque objet point possède une liste (habituellement structure liste chainée) de liens (des pointeurs) vers les points auxquels il est adjacent, ainsi que leur "distance" qui les sépare. En quelque sorte la liste d'adjacence d'un certain point comprend donc toutes les arêtes du graphe qui partent du point.

As-tu compris le principe de l'algorithme ? Si oui, alors tu sais qu'on a en fait besoin de connaitre les voisins pour chaque point qu'on regarde. La liste d'adjacence permet de le savoir très vite : pas besoin de parcourir toutes les arêtes du graphe et trouver celles qui passent par le point que tu regardes.

Mais par contre il faut construire la liste d'adjacence avant.
1
En faite mon graphe est composé de villes, et de kilomètre sur les arcs .
Mon problème c'est que je ne sais pas combien il faut de listes chainee ? une contenant le nom des sommets de départ et une pour énuméré tous les successeurs de chaque sommets ? et les valeurs dans tous ça, je les place ou ?

voici ma classe ListeChainee :

package projet;



public class ListeChaineeg implements Listeg
{
protected int lg;
protected Noeud tete;
protected Noeud queue;
protected Class typeDesElements;

public ListeChaineeg(Class c)
{
lg=0;
tete=null;
queue=null;
typeDesElements=c;
}

public void ajouterentete(Object e) throws Exception
{
Noeud n=new Noeud(e);
if (e.getClass() != typeDesElements) throw new Exception("erreur: type objet incorrect");
if (lg==0) {tete=n;queue=n;}
else {n.affectersuivant(tete);tete=n;}
lg++;
}

public void ajouterenqueue(Object e) throws Exception
{
if (e.getClass() != typeDesElements) throw new Exception("erreur: type objet incorrect");
Noeud n=new Noeud(e);
if (lg==0) {tete=n;queue=n;}
else {queue.affectersuivant(n);queue=n;}
lg++;
}

public void ajouterieme(int i,Object e) throws Exception
{
if (e.getClass() != typeDesElements) throw new Exception("erreur: type objet incorrect");
if (i>lg) throw new Exception("erreur: ajout � un rang impossible");
if (i==0) {ajouterentete(e);return;}
if (i==lg) {ajouterenqueue(e);return;}
Noeud n=tete;
Noeud p=new Noeud(e);
for (int j=1;j<=i-1;j++) n=n.accesnoeudSuivant();
p.affectersuivant(n.accesnoeudSuivant());
n.affectersuivant(p); lg++;
}

public void supprimerentete() throws Exception
{
if (estVide()) throw new Exception("erreur: supprimer un objet dans une liste vide");
tete=tete.accesnoeudSuivant();lg--;
}

public void supprimerenqueue() throws Exception
{
Noeud n=tete;
if (estVide()) throw new Exception("erreur: supprimer un objet dans une liste vide");
for(int i=1;i<lg-1;i++) n=n.accesnoeudSuivant();
n.affectersuivant(null);
queue=n;lg--;
}

public void supprimerieme(int i) throws Exception
{
if (i>=lg) throw new Exception("erreur: acc�s � un �l�ment inexistant");
if (i==0) {supprimerentete();return;}
if (i==lg-1) {supprimerenqueue();return;}
Noeud n=tete;
for (int j=1;j<=i-1;j++) n=n.accesnoeudSuivant();
n.affectersuivant(n.accesnoeudSuivant().lien);lg--;
}

public void remplacertete(Object e) throws Exception
{
supprimerentete();
ajouterentete(e);
}

public void remplacerqueue(Object e) throws Exception
{
supprimerenqueue();
ajouterenqueue(e);
}

public void remplacerieme(int i,Object e) throws Exception
{
supprimerieme(i);
ajouterieme(i,e);
}

public Object tete() throws Exception
{
if (estVide()) throw new Exception("erreur: atteindre la t�te d'une liste vide");
return(tete.valeur);
}

public Object queue() throws Exception
{
if (estVide()) throw new Exception("erreur: atteindre la queue d'une liste vide");
return(queue.valeur);
}

public boolean estVide()
{
return lg==0;
}

public int longueur()
{
return lg;
}

public void afficher()
{
if (lg==0) {System.out.println();return;}
System.out.print("LISTE CHAINEE : ");
Noeud n=tete;
for(int i=0;i<lg;i++)
{
System.out.print(n.valeur()+" ");
n=n.accesnoeudSuivant();
}
System.out.println();
}

public Object ieme(int i) throws Exception
{
if (i>=lg) throw new Exception("erreur: acc�s � un �l�ment inexistant");
Noeud n=tete;
for (int j=1;j<=i;j++) n=n.accesnoeudSuivant();
return(n.valeur());
}

public int pluspetitrang(Object e) throws Exception
{
if (estVide()) throw new Exception("erreur: supprimer un objet dans une liste vide");
if (!(appartient(e))) throw new Exception("erreur");
Noeud n=tete;
if(n.valeur.equals(e)) return 0;
for (int j=1;j<lg;j++)
{
n=n.accesnoeudSuivant();
if(n.valeur.equals(e)) return j;
}
return(100);
}

public boolean appartient(Object e)
{
if (lg==0) return false;
Noeud n=tete;
if (n.valeur.equals(e)) return true;
for (int j=1;j<lg;j++)
{
n=n.accesnoeudSuivant();
if (n.valeur.equals(e)) return true;
}
return false;
}

public Listeg concat(Listeg l) throws Exception
{
Listeg r=new ListeChaineeg(typeDesElements);
if (estVide()) return l;
Noeud n=tete;
r.ajouterentete(n.valeur);
for (int j=1;j<lg;j++)
{
n=n.accesnoeudSuivant();
r.ajouterenqueue(n.valeur);
}
for (int j=0;j<l.longueur();j++)
r.ajouterenqueue(l.ieme(j));
return r;
}

public Listeg souslistegauche(int i) throws Exception
{
return sousliste(0,i);
}

public Listeg souslistedroite(int i) throws Exception
{
return sousliste(i,lg-1);
}

public Listeg sousliste(int i, int j) throws Exception
{
if (i>=lg) throw new Exception("erreur: acc�s � un �l�ment inexistant");
if (j>=lg) throw new Exception("erreur: acc�s � un �l�ment inexistant");
if (i>j) throw new Exception("erreur: premier argument sup�rieur au second");
Listeg l=new ListeChaineeg(typeDesElements);
l.ajouterentete(ieme(i));
for (int k=i+1;k<=j;k++) l.ajouterenqueue(ieme(k));
return l;
}

}
1
Pacorabanix Messages postés 3248 Date d'inscription jeudi 23 août 2007 Statut Membre Dernière intervention 19 mai 2013 661
18 nov. 2009 à 20:48
bon, je suppose que ta classe liste chainée fonctionne correctement.

Ce que tu dois faire c'est la conception de la structure de donnée qui va maintenant "contenir" ton graphe.

Pour résumer : tu dois faire le "design" des classes qui te seront nécessaires.

Tout d'abord une classe graphe, qui comporte un tableau de Ville. La classe Ville (ou appelle ça comme tu voudras) est composée par exemple du nom de la ville ainsi que surtout d'une Liste d'adjacence. Dans cette liste on y indiquera toutes les villes qui sont reliées à sa propriétaire.

Un Liste D'adjacence est essentiellement une liste chainée, je ne pense pas que tu doives implémenter une classe pour spécialiser, ta classe que tu as faite suffira. Cette liste chainée est remplie avec des couples ville / distance qui relie la ville indiquée et la ville propriétaire de la liste. Ceci (le couple) pourrait éventuellement mériter une classe (la classe Arete par exemple, qui représente comme son nom l'indique une "arête" (ou un peu comme une flèche vers une autre ville).

Revenons au graphe.
Note que pour être efficace, la chose importante est de pouvoir accéder directement aux villes pointés par la liste d'adjacence. C'est pour cela que j'ai dit qu début que tu devrais stocker tes villes dans un tableau, ou dans toute autre structure permettant un accès rapide à tout élément (un arbre, par exemple, pourrait aussi faire l'affaire) mais en tout cas pas une liste chainée, car la liste chainée doit être parcourue avant de tomber sur le bon élément, la recherche d'un élément est O(n) en complexité


Ensuite, ton algorithme sera une méthode à appeler de la classe Graphe (CalculerPlusCourtsChemins(int indexVille)).

Note que l'algo "classique" (sans la forme matricielle) ne fonctionne malheureusement que pour un point en particulier, c'est à dire qu'un appel de cette fonction se fait en précisant un point de départ particulier. Ensuite l'algorithme calcule tous les plus courts chemins vers toutes les autres villes. Mais tu pourras sans souci faire une autre méthode "CalculerTout()" qui appelle l'autre méthode pour chaque point.

Tu peux intégrer dans ta classe Graphe les plus courts chemins ainsi calculés : par exemple, en plus d'un tableau de points que sont les villes, tu peux aussi avoir un tableau de tableaux de distances aux autres villes. A chaque ville correspondra un tableau avec les plus courtes distances vers chacune des autres villes.

La méthode CalculerPlusCourtsChemins() remplira donc le tableau d'une certaine ville.


Et aussi, l'initialisation de ton Graphe (en tant qu'objet) consistera à traduire les infos que tu as (villes et distances entre elles) en format correct (pour chaque ville tu crées un objet Ville en plus, et pour chaque distance entre deux villes données tu mets à jour les deux listes d'adjacences en créant une "arête" dans chaque.

Une fois que tu auras tes structures de données prêtes, l'algo se fera plus clairement et on pourra discuter de ça plus en détail si tu as besoin!

Bon courage.
0
Je pense avoir à peu près ma structure, je te la présente si dessous, et te demande de l'aide pour l'algo si possible ? Je l'ai compris ds l'ensemble mais pour l'implanter c'est autre chose ^^ ! Surtout que mon poid doit etre en fonction du temps ! (car je dispose des kilomètres et de la vitesse entre chaque villes pour le plus court chemin ) . J'ai regardé wiki, rien que lorsque je vois dans la fonction Initialisation : d[s] = infini . Je sais pas vraiment où se trouve mon d[s] à moi ^^ . Mercip de me répondre rapidement si possible ;)

public class ListeChaineeg implements Listeg
{
protected int lg;
protected Noeud tete;
protected Noeud queue;
protected Class typeDesElements;

public ListeChaineeg(Class c)
{
lg=0;
tete=null;
queue=null;
typeDesElements=c;
}

ListeChaineeg(ListeChaineeg courant) {
throw new UnsupportedOperationException("Not yet implemented");
}

public void ajouterentete(Object e) throws Exception
{
Noeud n=new Noeud(e);
if (e.getClass() != typeDesElements) throw new Exception("erreur: type objet incorrect");
if (lg==0) {tete=n;queue=n;}
else {n.affectersuivant(tete);tete=n;}
lg++;
}

public void ajouterenqueue(Object e) throws Exception
{
if (e.getClass() != typeDesElements) throw new Exception("erreur: type objet incorrect");
Noeud n=new Noeud(e);
if (lg==0) {tete=n;queue=n;}
else {queue.affectersuivant(n);queue=n;}
lg++;
}

public void ajouterieme(int i,Object e) throws Exception
{
if (e.getClass() != typeDesElements) throw new Exception("erreur: type objet incorrect");
if (i>lg) throw new Exception("erreur: ajout � un rang impossible");
if (i==0) {ajouterentete(e);return;}
if (i==lg) {ajouterenqueue(e);return;}
Noeud n=tete;
Noeud p=new Noeud(e);
for (int j=1;j<=i-1;j++) n=n.accesnoeudSuivant();
p.affectersuivant(n.accesnoeudSuivant());
n.affectersuivant(p); lg++;
}

public void supprimerentete() throws Exception
{
if (estVide()) throw new Exception("erreur: supprimer un objet dans une liste vide");
tete=tete.accesnoeudSuivant();lg--;
}

public void supprimerenqueue() throws Exception
{
Noeud n=tete;
if (estVide()) throw new Exception("erreur: supprimer un objet dans une liste vide");
for(int i=1;i<lg-1;i++) n=n.accesnoeudSuivant();
n.affectersuivant(null);
queue=n;lg--;
}

public void supprimerieme(int i) throws Exception
{
if (i>=lg) throw new Exception("erreur: acc�s � un �l�ment inexistant");
if (i==0) {supprimerentete();return;}
if (i==lg-1) {supprimerenqueue();return;}
Noeud n=tete;
for (int j=1;j<=i-1;j++) n=n.accesnoeudSuivant();
n.affectersuivant(n.accesnoeudSuivant().lien);lg--;
}

public void remplacertete(Object e) throws Exception
{
supprimerentete();
ajouterentete(e);
}

public void remplacerqueue(Object e) throws Exception
{
supprimerenqueue();
ajouterenqueue(e);
}

public void remplacerieme(int i,Object e) throws Exception
{
supprimerieme(i);
ajouterieme(i,e);
}

public Object tete() throws Exception
{
if (estVide()) throw new Exception("erreur: atteindre la t�te d'une liste vide");
return(tete.valeur);
}

public Object queue() throws Exception
{
if (estVide()) throw new Exception("erreur: atteindre la queue d'une liste vide");
return(queue.valeur);
}

public boolean estVide()
{
return lg==0;
}

public int longueur()
{
return lg;
}

public void afficher()
{
if (lg==0) {System.out.println();return;}
System.out.print("LISTE CHAINEE : ");
Noeud n=tete;
for(int i=0;i<lg;i++)
{
System.out.print(n.valeur()+" ");
n=n.accesnoeudSuivant();
}
System.out.println();
}

public Object ieme(int i) throws Exception
{
if (i>=lg) throw new Exception("erreur: acc�s � un �l�ment inexistant");
Noeud n=tete;
for (int j=1;j<=i;j++) n=n.accesnoeudSuivant();
return(n.valeur());
}

public int pluspetitrang(Object e) throws Exception
{
if (estVide()) throw new Exception("erreur: supprimer un objet dans une liste vide");
if (!(appartient(e))) throw new Exception("erreur");
Noeud n=tete;
if(n.valeur.equals(e)) return 0;
for (int j=1;j<lg;j++)
{
n=n.accesnoeudSuivant();
if(n.valeur.equals(e)) return j;
}
return(100);
}

public boolean appartient(Object e)
{
if (lg==0) return false;
Noeud n=tete;
if (n.valeur.equals(e)) return true;
for (int j=1;j<lg;j++)
{
n=n.accesnoeudSuivant();
if (n.valeur.equals(e)) return true;
}
return false;
}

public Listeg concat(Listeg l) throws Exception
{
Listeg r=new ListeChaineeg(typeDesElements);
if (estVide()) return l;
Noeud n=tete;
r.ajouterentete(n.valeur);
for (int j=1;j<lg;j++)
{
n=n.accesnoeudSuivant();
r.ajouterenqueue(n.valeur);
}
for (int j=0;j<l.longueur();j++)
r.ajouterenqueue(l.ieme(j));
return r;
}

public Listeg souslistegauche(int i) throws Exception
{
return sousliste(0,i);
}

public Listeg souslistedroite(int i) throws Exception
{
return sousliste(i,lg-1);
}

public Listeg sousliste(int i, int j) throws Exception
{
if (i>=lg) throw new Exception("erreur: acc�s � un �l�ment inexistant");
if (j>=lg) throw new Exception("erreur: acc�s � un �l�ment inexistant");
if (i>j) throw new Exception("erreur: premier argument sup�rieur au second");
Listeg l=new ListeChaineeg(typeDesElements);
l.ajouterentete(ieme(i));
for (int k=i+1;k<=j;k++) l.ajouterenqueue(ieme(k));
return l;
}

}





package i3a;

public class ListeTableaug implements Listeg
{
protected static final int MAXELEM=100;
protected int lg;
protected Object[] elements;
protected Class typeDesElements;

public ListeTableaug(Class c)
{
this(MAXELEM,c);
lg=0;
typeDesElements=c;
}

public ListeTableaug(int n,Class c)
{
elements=new Object[n];
lg=0;
typeDesElements=c;
}

public void ajouterentete(Object e) throws Exception
{
if (e.getClass() != typeDesElements) throw new Exception("erreur: type objet incorrect");
if (lg==elements.length) throw new Exception("Liste pleine");
for(int i=lg;i>=1;i--) elements[i]=elements[i-1];
elements[0]=e;
lg++;
}
public void ajouterenqueue(Object e) throws Exception
{
if (e.getClass() != typeDesElements) throw new Exception("erreur: type objet incorrect");
if (lg==elements.length) throw new Exception("Liste pleine");
elements[lg]=e;
lg++;
}
public void ajouterieme(int r,Object e) throws Exception
{
if (e.getClass() != typeDesElements) throw new Exception("erreur: type objet incorrect");
if (lg==elements.length) throw new Exception("Liste pleine");
if (r<0 || r>lg) throw new Exception("erreur: ajout � un rang impossible");
for(int i=lg;i>r;i--) elements[i]=elements[i-1];
elements[r]=e;
lg++;
}

public void supprimerentete() throws Exception
{
if (estVide()) throw new Exception("erreur: supprimer un objet dans une liste vide");
for(int i=1;i<lg;i++) elements[i-1]=elements[i];
lg--;
}
public void supprimerenqueue() throws Exception
{
if (estVide()) throw new Exception("erreur: supprimer un objet dans une liste vide");
lg--;
}
public void supprimerieme(int r) throws Exception
{
if (estVide()) throw new Exception("erreur: supprimer un objet dans une liste vide");
if (r<0 || r>=lg) throw new Exception("erreur: acces � un rang impossible");
for (int i=r;i<lg-1;i++) elements[i]=elements[i+1];
lg--;
}

public void remplacertete(Object e) throws Exception
{
supprimerentete();
ajouterentete(e);
}
public void remplacerqueue(Object e) throws Exception
{
supprimerenqueue();
ajouterenqueue(e);
}
public void remplacerieme(int r,Object e) throws Exception
{
supprimerieme(r);
ajouterieme(r,e);
}

public Object tete() throws Exception
{
if (estVide()) throw new Exception("erreur: atteindre la t�te d'une liste vide");
return(elements[0]);
}
public Object queue() throws Exception
{
if (estVide()) throw new Exception("erreur: atteindre la queue d'une liste vide");
return(elements[lg-1]);
}
public boolean estVide()
{
return lg==0;
}
public int longueur()
{
return lg;
}
public void afficher()
{
if (lg==0) {System.out.println();return;}
System.out.print("LISTE TABLEAU : ");
for (int i=0;i<lg;i++) System.out.print(elements[i]+" ");
System.out.println();

}
public Object ieme(int r) throws Exception
{
if (r<0 || r>lg-1) throw new Exception("erreur: acces � un rang impossible");
return elements[r];
}

public int pluspetitrang(Object e) throws Exception
{
if (estVide()) throw new Exception("erreur: supprimer un objet dans une liste vide");
if (!(appartient(e))) throw new Exception("erreur");
if(elements[0].equals(e)) return 0;
for (int j=1;j<lg;j++)
if(elements[j].equals(e)) return j;
return(100);
}
public boolean appartient(Object e)
{
if (lg==0) return false;
for (int j=0;j<lg;j++)
if (elements[j].equals(e)) return true;
return false;
}
public Listeg concat(Listeg l) throws Exception
{
Listeg r=new ListeTableaug(typeDesElements);
if (estVide()) return l;
r.ajouterentete(elements[0]);
for (int j=1;j<lg;j++)
r.ajouterenqueue(elements[j]);
for (int j=0;j<l.longueur();j++)
r.ajouterenqueue(l.ieme(j));
return r;
}
public Listeg souslistegauche(int r) throws Exception
{
return sousliste(0,r);
}
public Listeg souslistedroite(int r) throws Exception
{
return sousliste(r,lg-1);
}
public Listeg sousliste(int r,int s) throws Exception
{
if (r>=lg) throw new Exception("erreur: acc�s � un �l�ment inexistant");
if (s>=lg) throw new Exception("erreur: acc�s � un �l�ment inexistant");
if (r>s) throw new Exception("erreur: premier argument sup�rieur au second");
Listeg l=new ListeTableaug(typeDesElements);
l.ajouterentete(ieme(r));
for (int k=r+1;k<=s;k++) l.ajouterenqueue(ieme(k));
return l;
}

}




package i3a;

public class Noeud extends Lien
{
protected Object valeur;
public Noeud(Object e) {valeur=e;}
public Noeud(Object e, Noeud s) {valeur=e;affectersuivant(s);}
public Object valeur() {return valeur;}
public void changerValeur(Object e) {valeur=e;}
public Noeud accesnoeudSuivant() {return (Noeud) accessuivant();}
public void affecternoeudSuivant(Noeud s) {affectersuivant(s);}
}



package i3a;

public class Lien {

protected Lien lien;
protected Lien accessuivant() {return lien;}
protected void affectersuivant(Lien s) {lien=s;}

}



/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/

package i3a;

import java.io.FileNotFoundException;

/**
*
* @author
*/
public class Ville {
String nom;


public Ville (String inom) throws FileNotFoundException{
nom=inom;

}


public String getNom (){
return nom;
}
}



/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/

package i3a;

/**
*
* @author
*/
public class Iterateur {
ListeChaineeg courant;

public Iterateur (Iterateur iter){
this.courant=new ListeChaineeg (iter.courant);
}
// Associer l'itérateur avec un sommet donné du graphe
// L'itérateur désigne alors le premier voisin (voisin courant)
public Iterateur (Graphe g, Ville ville){

}

//Avancer l'itérateur sur le voisin suivant
public void avancer(){

}

/*//indiquer qu'il n'y a plus de sommet voisin
public boolean termine(){

}

//Redonner le sommet voisin courant designé par l'itérateur
public Ville voisinDe(){

}

//Redonner l'attribut de l'arc se treminant
// au voisin designe par l'iterateur
public int attributDe (){

}*/

}



/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/

package i3a;

/**
*
* @author
*/
public class Graphe {
public int nbrVilles;
public ListeChaineeg[] listes;
public Ville [] villes;

public Graphe (){
nbrVilles=villes.length;
//Tableau de listes
listes = new ListeChaineeg [nbrVilles];
villes=new Ville [nbrVilles];
//Tableau des sommets
for (int i = 0; i<nbrVilles; i++){
listes[i]=new ListeChaineeg(Ville.class); // ou Successeur.class
}

}

// Effacer tous les éléments d'un graphe et en faire un vide
public void effacer (){}

//ajouter un sommet au graphe
public void inserer (Ville laVille){}

//modifier le nom d'un sommet du graphe
public void modifierSommet (Ville ville, String e){}

//Relier le sommet sommetInitial au sommet sommetTerminal par
// un arc de poids attribut (dist, vit)
public void relier (Ville villeInitiale, Ville villeTerminale, int dist, int vit){}

/* //indiquer si le graphe est vide
public boolean estVide(){}

//indiquer si un sommet appartient au graphe
public boolean sommetDefini (Ville ville){}

//Retouner le sommet de nom donne
public Ville villeDeNom (int i){}

//retourne le nbr de sommet ds le graphe
public int nbVilles (){}*/

}


/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/

package i3a;

/**
*
* @author
*/
public class Dijkstra {

public void Initialisation (Graphe g, Ville sdeb){
for (int i=0; i<g.nbrVilles; i++){
// distance
}
}
}



Sachant que j'aurai une classe Flux en plus , histoire de remplir tous ca avec 2 fichiers txt.
Merci
0