septembre
2010
J’ai eu besoin d’utiliser l’algo bien connu de Dijkstra pour trouver un plus court chemin entre 2 points. Le principe est très bien expliqué sur wikipédia, mais j’avais besoin d’une implémentation en C.
Après quelques recherches, je suis tombé sur cette page qui m’offre l’aglo tout cuit, mais sans son utilisation.
Je montre ici comment l’utiliser après une ou deux corrections de coquille dans l’algo trouvé.
Il faut dans un premier temps une matrice adjacente, qui peut être de cette forme :
1: #define INFINI 10000
2: #define NB_SOMMET 6
3:
4: int mat[NB_SOMMET][NB_SOMMET] =
5: {{ 0, 171, INFINI, INFINI, INFINI, INFINI},
6: {171, 0, 30, INFINI, INFINI, INFINI},
7: {INFINI, 30, 0, INFINI, 39, 13},
8: {INFINI, INFINI, INFINI, 0, 30, INFINI},
9: {INFINI, INFINI, 39, 30, 0, 26},
10: {INFINI, INFINI, 13, INFINI, 26, 0}};
On a une constante “Infini” qui est suffisamment grande, c’est à dire plus grande que la distance maxi entre 2 sommets. Et une matrice carrée contenant la distance entre chaque sommet.
Ensuite la méthode avec les 2-3 trucs corrigés :
1: void dodijkstra(int sr,int ds, int path[])
2: {
3: if (sr == ds)
4: return;
5:
6: struct node
7: {
8: int pre; /* Predecessor */
9: int length; /* Length between the nodes */
10: enum {perm,tent} label; /* Enumeration for permanent and tentative labels */
11: }state[NB_SOMMET];
12:
13: int i,k,min;
14: struct node *p;
15: /* Initialisation of the nodes aka First step of Dijkstra Algo */
16: for(p=&state[0];p<&state[NB_SOMMET];p++)
17: {
18: p->pre= -1;
19: p->length=INFINI;
20: p->label=node::tent;
21: }
22: state[ds].length=0; /* Destination length set to zero */
23: state[ds].label=node::perm; /* Destination set to be the permanent node */
24: k=ds; /* initial working node */
25: /* Checking for a better path from the node k ? */
26: do
27: {
28: for(i=0;i<NB_SOMMET;i++)
29: {
30: if(mat[k][i]!=0 && state[i].label==node::tent)
31: {
32: if((state[k].length+mat[k][i])<state[i].length)
33: {
34: state[i].pre=k;
35: state[i].length=state[k].length+mat[k][i];
36: }
37: }
38: }
39: k=0;
40: min=INFINI;
41: /* Find a node which is tentatively labeled and with minimum label */
42: for(i=0;i<NB_SOMMET;i++)
43: {
44: if(state[i].label==node::tent && state[i].length<min)
45: {
46: min=state[i].length;
47: k=i;
48: }
49: }
50: state[k].label=node::perm;
51: } while(k!=sr);
52:
53: i=0;
54: k=sr;
55: /* Print the path to the output array */
56: do
57: {
58: path[i++]=k;
59: k=state[k].pre;
60: } while(k>=0);
61: path[i]=k;
62: }
et enfin, l’appel de la méthode :
1: int path[150];
2: for (int z = 0 ; z < 150 ; z++)
3: path[z] = -1;
4: dodijkstra(sommetSource, sommetDestination, path);
On initialise le tableau de résultat. Ici j’ai pris 150 arbitrairement, le but est que le tableau puisse contenir toutes les étapes intermédiaires.
L’algorithme nous rempli le tableau avec le trajet optimal.
path[0] contiendra la source
path[i] contient les différents sommets intermédiaires
path[n] contient la destination
path[n->150] contient -1
Simple et efficace !
Commentaires récents
- [Tests] Arrange Act Assert, une traduction ? dans
- [UnitTest][C#] Tester une méthode privée dans
- Récupérer une valeur d’un contrôle depuis une autre Form / inclusions croisées et déclaration anticipée dans
- Tutoriel : Utiliser la ListBox et l’Isolated Storage dans vos applications Windows Phone 7 avec Silverlight dans
- Tutoriel : Utiliser la ListBox et l’Isolated Storage dans vos applications Windows Phone 7 avec Silverlight dans
Archives
- janvier 2013
- avril 2012
- janvier 2012
- juin 2011
- janvier 2011
- décembre 2010
- novembre 2010
- septembre 2010
- juin 2010
- mars 2010
- février 2010
- janvier 2010
- décembre 2009
- novembre 2009
- octobre 2009
- septembre 2009
- août 2009
- juillet 2009
- mai 2009
- avril 2009
- mars 2009
- janvier 2009
- décembre 2008
- novembre 2008
- octobre 2008
- septembre 2008
- août 2008
- juillet 2008
- juin 2008
- mai 2008
- avril 2008
- mars 2008
- février 2008
- janvier 2008
- décembre 2007
- novembre 2007
- octobre 2007
- septembre 2007
- août 2007
- juillet 2007
- juin 2007
- mai 2007