00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "bfs.h"
00028 #include "dijkstra.h"
00029 #include <limits.h>
00030 #include <stdlib.h>
00031
00032
00033 #define MAX_DIST (double)INT_MAX
00034
00035 typedef DistType Word;
00036
00037 #define LOOP while(TRUE)
00038
00039
00040
00041
00042
00043 #define left(i) (2*(i))
00044 #define right(i) (2*(i)+1)
00045 #define parent(i) ((i)/2)
00046 #define insideHeap(h,i) ((i)<h->heapSize)
00047 #define greaterPriority(h,i,j,dist) (dist[h->data[i]]<dist[h->data[j]])
00048 #define assign(h,i,j,index) {h->data[i]=h->data[j]; index[h->data[i]]=i;}
00049 #define exchange(h,i,j,index) {int temp; \
00050 temp=h->data[i]; \
00051 h->data[i]=h->data[j]; \
00052 h->data[j]=temp; \
00053 index[h->data[i]]=i; \
00054 index[h->data[j]]=j; \
00055 }
00056
00057 typedef struct {
00058 int *data;
00059 int heapSize;
00060 } heap;
00061
00062 static void heapify(heap * h, int i, int index[], Word dist[])
00063 {
00064 int l, r, largest;
00065 while (1) {
00066 l = left(i);
00067 r = right(i);
00068 if (insideHeap(h, l) && greaterPriority(h, l, i, dist))
00069 largest = l;
00070 else
00071 largest = i;
00072 if (insideHeap(h, r) && greaterPriority(h, r, largest, dist))
00073 largest = r;
00074
00075 if (largest == i)
00076 break;
00077
00078 exchange(h, largest, i, index);
00079 i = largest;
00080 }
00081 }
00082
00083 #ifdef OBSOLETE
00084
00085
00086
00087
00088 static void mkHeap(heap * h, int size)
00089 {
00090 h->data = N_GNEW(size, int);
00091 h->heapSize = 0;
00092 }
00093 #endif
00094
00095 static void freeHeap(heap * h)
00096 {
00097 if (h->data) free(h->data);
00098 }
00099
00100 static void
00101 initHeap(heap * h, int startVertex, int index[], Word dist[], int n)
00102 {
00103 int i, count;
00104 int j;
00105
00106 if (n == 1) h->data = NULL;
00107 else h->data = N_GNEW(n - 1, int);
00108 h->heapSize = n - 1;
00109
00110 for (count = 0, i = 0; i < n; i++)
00111 if (i != startVertex) {
00112 h->data[count] = i;
00113 index[i] = count;
00114 count++;
00115 }
00116
00117 for (j = (n - 1) / 2; j >= 0; j--)
00118 heapify(h, j, index, dist);
00119 }
00120
00121 static boolean extractMax(heap * h, int *max, int index[], Word dist[])
00122 {
00123 if (h->heapSize == 0)
00124 return FALSE;
00125
00126 *max = h->data[0];
00127 h->data[0] = h->data[h->heapSize - 1];
00128 index[h->data[0]] = 0;
00129 h->heapSize--;
00130 heapify(h, 0, index, dist);
00131
00132 return TRUE;
00133 }
00134
00135 static void
00136 increaseKey(heap * h, int increasedVertex, Word newDist, int index[],
00137 Word dist[])
00138 {
00139 int placeInHeap;
00140 int i;
00141
00142 if (dist[increasedVertex] <= newDist)
00143 return;
00144
00145 placeInHeap = index[increasedVertex];
00146
00147 dist[increasedVertex] = newDist;
00148
00149 i = placeInHeap;
00150 while (i > 0 && dist[h->data[parent(i)]] > newDist) {
00151 assign(h, i, parent(i), index);
00152 i = parent(i);
00153 }
00154 h->data[i] = increasedVertex;
00155 index[increasedVertex] = i;
00156 }
00157
00158 void dijkstra(int vertex, vtx_data * graph, int n, DistType * dist)
00159 {
00160 int i;
00161 heap H;
00162 int closestVertex, neighbor;
00163 DistType closestDist, prevClosestDist = INT_MAX;
00164 static int *index;
00165
00166 #ifdef OBSOLETE
00167 mkHeap(&H, n);
00168 #endif
00169 index = (int *) realloc(index, n * sizeof(int));
00170
00171
00172 for (i = 0; i < n; i++)
00173 dist[i] = (DistType) MAX_DIST;
00174 dist[vertex] = 0;
00175 for (i = 1; i < graph[vertex].nedges; i++)
00176 dist[graph[vertex].edges[i]] = (DistType) graph[vertex].ewgts[i];
00177
00178 initHeap(&H, vertex, index, dist, n);
00179
00180 while (extractMax(&H, &closestVertex, index, dist)) {
00181 closestDist = dist[closestVertex];
00182 if (closestDist == MAX_DIST)
00183 break;
00184 for (i = 1; i < graph[closestVertex].nedges; i++) {
00185 neighbor = graph[closestVertex].edges[i];
00186 increaseKey(&H, neighbor,
00187 closestDist +
00188 (DistType) graph[closestVertex].ewgts[i], index,
00189 dist);
00190 }
00191 prevClosestDist = closestDist;
00192 }
00193
00194
00195 for (i = 0; i < n; i++)
00196 if (dist[i] == MAX_DIST)
00197 dist[i] = prevClosestDist + 10;
00198 freeHeap(&H);
00199 }
00200
00201
00202 int
00203 dijkstra_bounded(int vertex, vtx_data * graph, int n, DistType * dist,
00204 int bound, int *visited_nodes)
00205
00206
00207
00208 {
00209 int num_visited_nodes;
00210 int i;
00211 static boolean *node_in_neighborhood = NULL;
00212 static int size = 0;
00213 static int *index;
00214 Queue Q;
00215 heap H;
00216 int closestVertex, neighbor;
00217 DistType closestDist;
00218 int num_found = 0;
00219
00220
00221 mkQueue(&Q, n);
00222
00223 for (i = 0; i < n; i++) {
00224 dist[i] = -1;
00225 }
00226 num_visited_nodes =
00227 bfs_bounded(vertex, graph, n, dist, &Q, bound, visited_nodes);
00228 if (size < n) {
00229 node_in_neighborhood =
00230 (boolean *) realloc(node_in_neighborhood, n * sizeof(boolean));
00231 for (i = size; i < n; i++) {
00232 node_in_neighborhood[i] = FALSE;
00233 }
00234 size = n;
00235 }
00236 for (i = 0; i < num_visited_nodes; i++) {
00237 node_in_neighborhood[visited_nodes[i]] = TRUE;
00238 }
00239
00240
00241 #ifdef OBSOLETE
00242 mkHeap(&H, n);
00243 #endif
00244 index = (int *) realloc(index, n * sizeof(int));
00245
00246
00247 for (i = 0; i < n; i++)
00248 dist[i] = (DistType) MAX_DIST;
00249 dist[vertex] = 0;
00250 for (i = 1; i < graph[vertex].nedges; i++)
00251 dist[graph[vertex].edges[i]] = (DistType) graph[vertex].ewgts[i];
00252
00253
00254 initHeap(&H, vertex, index, dist, n);
00255
00256 while (num_found < num_visited_nodes
00257 && extractMax(&H, &closestVertex, index, dist)) {
00258 if (node_in_neighborhood[closestVertex]) {
00259 num_found++;
00260 }
00261 closestDist = dist[closestVertex];
00262 if (closestDist == MAX_DIST)
00263 break;
00264 for (i = 1; i < graph[closestVertex].nedges; i++) {
00265 neighbor = graph[closestVertex].edges[i];
00266 increaseKey(&H, neighbor,
00267 closestDist +
00268 (DistType) graph[closestVertex].ewgts[i], index,
00269 dist);
00270 }
00271 }
00272
00273
00274 for (i = 0; i < num_visited_nodes; i++) {
00275 node_in_neighborhood[visited_nodes[i]] = FALSE;
00276 }
00277 freeHeap(&H);
00278 freeQueue(&Q);
00279 return num_visited_nodes;
00280 }
00281
00282 static void heapify_f(heap * h, int i, int index[], float dist[])
00283 {
00284 int l, r, largest;
00285 while (1) {
00286 l = left(i);
00287 r = right(i);
00288 if (insideHeap(h, l) && greaterPriority(h, l, i, dist))
00289 largest = l;
00290 else
00291 largest = i;
00292 if (insideHeap(h, r) && greaterPriority(h, r, largest, dist))
00293 largest = r;
00294
00295 if (largest == i)
00296 break;
00297
00298 exchange(h, largest, i, index);
00299 i = largest;
00300 }
00301 }
00302
00303 static void
00304 initHeap_f(heap * h, int startVertex, int index[], float dist[], int n)
00305 {
00306 int i, count;
00307 int j;
00308 h->data = N_GNEW(n - 1, int);
00309 h->heapSize = n - 1;
00310
00311 for (count = 0, i = 0; i < n; i++)
00312 if (i != startVertex) {
00313 h->data[count] = i;
00314 index[i] = count;
00315 count++;
00316 }
00317
00318 for (j = (n - 1) / 2; j >= 0; j--)
00319 heapify_f(h, j, index, dist);
00320 }
00321
00322 static boolean extractMax_f(heap * h, int *max, int index[], float dist[])
00323 {
00324 if (h->heapSize == 0)
00325 return FALSE;
00326
00327 *max = h->data[0];
00328 h->data[0] = h->data[h->heapSize - 1];
00329 index[h->data[0]] = 0;
00330 h->heapSize--;
00331 heapify_f(h, 0, index, dist);
00332
00333 return TRUE;
00334 }
00335
00336 static void
00337 increaseKey_f(heap * h, int increasedVertex, float newDist, int index[],
00338 float dist[])
00339 {
00340 int placeInHeap;
00341 int i;
00342
00343 if (dist[increasedVertex] <= newDist)
00344 return;
00345
00346 placeInHeap = index[increasedVertex];
00347
00348 dist[increasedVertex] = newDist;
00349
00350 i = placeInHeap;
00351 while (i > 0 && dist[h->data[parent(i)]] > newDist) {
00352 assign(h, i, parent(i), index);
00353 i = parent(i);
00354 }
00355 h->data[i] = increasedVertex;
00356 index[increasedVertex] = i;
00357 }
00358
00359
00360
00361
00362
00363 void dijkstra_f(int vertex, vtx_data * graph, int n, float *dist)
00364 {
00365 int i;
00366 heap H;
00367 int closestVertex = 0, neighbor;
00368 float closestDist;
00369 int *index;
00370
00371 #ifdef OBSOLETE
00372 mkHeap(&H, n);
00373 #endif
00374 index = N_GNEW(n, int);
00375
00376
00377 for (i = 0; i < n; i++)
00378 dist[i] = MAXFLOAT;
00379 dist[vertex] = 0;
00380 for (i = 1; i < graph[vertex].nedges; i++)
00381 dist[graph[vertex].edges[i]] = graph[vertex].ewgts[i];
00382
00383 initHeap_f(&H, vertex, index, dist, n);
00384
00385 while (extractMax_f(&H, &closestVertex, index, dist)) {
00386 closestDist = dist[closestVertex];
00387 if (closestDist == MAXFLOAT)
00388 break;
00389 for (i = 1; i < graph[closestVertex].nedges; i++) {
00390 neighbor = graph[closestVertex].edges[i];
00391 increaseKey_f(&H, neighbor,
00392 closestDist + graph[closestVertex].ewgts[i],
00393 index, dist);
00394 }
00395 }
00396
00397 freeHeap(&H);
00398 free(index);
00399 }