Bonjour

j'ai trouvé un programme en C sur l'algo du Dijkstra du plus court chemin
Le programme marche mais que je ne comprend pas trop comment il se déroule.

l'algorithme lui se trouve ici :
http://fr.wikipedia.org/wiki/Algorit...ra#Pseudo-code

Pourriez vous m'expliquer s'il vou plait comment fonctionne ce programme?
je l'ai compilé en C sur devc++
je n'ai pas compris le role de toutes les matrices, ainsi que du booléen et le "array_D"

merci :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
 
#include <stdio.h>
#include <limits.h>
#include <assert.h>
 
typedef enum {false, true} bool; /* The order is rather important to
                                    get the boolean values right. */
typedef char *string;
 
#define oo UINT_MAX /* infinity is represented as the maximum unsigned int. */
 
typedef unsigned int value;
 
/* Firstly, the type of vertices for our particular graph (which was
   given as an example in the lectures). The (non)vertex `nonexistent'
   is used in order to indicate that a vertex (un sommet) hasn't got a predecessor
   in the path under consideration. See below. */
 
typedef enum { A, B, C, D, nonexistent} vertex;
 
/* If you modify the above, in order to consider a different graph,
   then you also have to modify the following. */
 
const vertex first_vertex = A;
const vertex last_vertex = D;
 
#define no_vertices 4 // nombre de sommets
 
/* Now a dictionary for output purposes. The order has to match the
   above, so that, for example, name[SFO]="SFO". */
 
string name[] = {"A","B","C","D"};
 
value weight[no_vertices][no_vertices] =
  {
   /*  A    B    C    D */
    {    0,   1,  2,  oo},  /* A */
    {   oo,   0,  1,   4},  /* B */
    {   oo,  oo,  0,   3},  /* C */
    {   2,   oo, oo,   0}   /* D */
  };
 
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *     
 * The implementation of Dijkstra's algorithm starts here. *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
/* We first declare the array (ordre) `array_D' of overestimates, the array `tight' (serré)
   which records which of those estimates are actually tight, and the
   array `predecessor'. The last has the property that predecessor[z]
   is the last vertex visited on the way from the start node to z. */
 
value array_D[no_vertices];          // coûts ou valeurs
bool tight[no_vertices];
vertex predecessor[no_vertices];    // sommets
 
/* 
  We begin with the following auxiliary function, which should be
  called only when we know for sure that there is at least one node u
  with tight[u] false. Otherwise, the program aborts; this happens
  when the assertion below fails.
 */
 
vertex minimal_nontight() {
 
  vertex j, u;
 
  for (j = first_vertex; j <= last_vertex; j++) 
     if (!tight[j]) 
        break;
 
  assert(j <= last_vertex);  // vérification que j est bien inférieur à last_vertex
 
  u = j; 
 
 /* Now u is the first vertex with nontight estimate, but not
     necessarily the one with minimal estimate, so we aren't done
     yet. */
 
  for (j++; j <= last_vertex; j++)
     if (!tight[j]  &&  array_D[j] < array_D[u])
          u = j;
 
  /* Having checked all vertices, we now know that u has the required
     minimality property. */ 
 
  return u;
}
 
/* 
   The following definition assumes that the graph is directed in
   general, which means that it would be wrong to have weight[z][u]
   instead. The intended meaning is that the vertex u has the vertex z
   as one of its successors. Recall that such a vertex z was
   called a neighbour of the vertex u, but this latter terminology is
   best reserved for undirected graphs. Notice that the example given
   above happens to be undirected. But, as remarked above, this
   program is intended to work for directed graphs as well. 
 */
 
bool successor(vertex u, vertex z) {
  return (weight[u][z] != oo  &&  u != z);
}
 
 
/* 
  We finally arrive at the main algorithm. This is the same as given
  above, now written in C, with the computation of the actual
  paths included. The computation of paths is achieved via the use of
  the array `predecessor' declared above. Strictly speaking,
  Dijkstra's algorithm only records what is needed in order to recover
  the path. The actual computation of the path is performed by the
  algorithm that follows it.
 */
 
void dijkstra(vertex s) {
 
  vertex z, u;
  int i;
 
  array_D[s] = 0;
 
  for (z = first_vertex; z <= last_vertex; z++) {
 
    if (z != s)
      array_D[z] = oo;
 
    tight[z] = false;
    predecessor[z] = nonexistent;
  }
 
  for (i = 0; i < no_vertices; i++) {
 
    u = minimal_nontight();
    tight[u] = true;
 
    /* In a disconnected graph, array_D[u] can be oo. But then we just move
       on to the next iteration of the loop. (Can you see why?) */
 
    if (array_D[u] == oo)
      continue; /* to next iteration ofthe for loop */
 
    for (z = first_vertex; z <= last_vertex; z++)
      if (successor(u,z) && !tight[z] && array_D[u] + weight[u][z] < array_D[z]) {
        array_D[z] = array_D[u] + weight[u][z]; /* Shortcut found. */
        predecessor[z] = u;
      }
  }
}
 
/* The conditions (successor(u,z) && !tight[z]) can be omitted from
   the above algorithm without changing its correctness. But I think
   that the algorithm is clearer with the conditions included, because
   it makes sense to attempt to tighten the estimate for a vertex only
   if the vertex is not known to be tight and if the vertex is a
   successor of the vertex under consideration. Otherwise, the
   condition (array_D[u] + weight[u][z] < array_D[z]) will fail anyway. However,
   in practice, it may be more efficient to just remove the conditions
   and only perform the test (array_D[u] + weight[u][z] < array_D[z]). */
 
/* We can now use Dijkstra's algorithm to compute the shortest path
   between two given vertices. It is easy to go from the end of the
   path to the beginning. 
 
   To reverse the situation, we use a stack. Therefore we digress
   slightly to implement stacks (of vertices). In practice, one is
   likely to use a standard library instead, but, for teaching
   purposes, I prefer this program to be selfcontained. */
 
 
#define stack_limit 10000 /* Arbitrary choice. Has to be big enough to
                             accomodate the largest path. */
 
vertex stack[stack_limit];
unsigned int sp = 0; /* Stack pointer. */
 
void push(vertex u) {
  assert(sp < stack_limit); /* We abort if the limit is exceeded. This
                               will happen if a path with more
                               vertices than stack_limit is found. */
  stack[sp] = u;
  sp++;
}
 
bool stack_empty() {
  return (sp == 0);
}
 
vertex pop() {
  assert(!stack_empty()); /* We abort if the stack is empty. This will
                             happen if this program has a bug. */
  sp--;
  return stack[sp];
}
 
/* End of stack digression and back to printing paths. */
 
 
void print_shortest_path(vertex origin, vertex destination) {
 
  vertex v;
 
  assert(origin != nonexistent  &&  destination != nonexistent);
 
  dijkstra(origin);
 
  printf("The shortest path from %s to %s is:\n\n",
         name[origin], name[destination]);
 
  for (v = destination; v != origin; v = predecessor[v])
    if (v == nonexistent) {
      printf("nonexistent (because the graph is disconnected).\n");
      return;
    }
    else
      push(v);
 
  push(origin); 
 
  while (!stack_empty()) 
    printf(" %s",name[pop()]);
 
  printf(".\n\n");
}
 
 
/* We now run an example. */
 
int main() {
 
  print_shortest_path(C,A);   // de C à A
  getch();
  return 0; /* Return gracefully to the caller of the program
               (provided the assertions above haven't failed). */
}
merci