Dijkstra's algorithm: Difference between revisions
Content added Content deleted
(→{{header|C}}: no longer that extra test case) |
(→{{header|C}}: do not store vertex index in the vertex) |
||
Line 367: | Line 367: | ||
#include <stdlib.h> |
#include <stdlib.h> |
||
#include <limits.h> |
#include <limits.h> |
||
#include <stdarg.h> |
|||
typedef struct { |
typedef struct { |
||
Line 374: | Line 375: | ||
typedef struct { |
typedef struct { |
||
edge_t ** |
edge_t **edges; |
||
int |
int edges_len; |
||
int |
int edges_size; |
||
⚫ | |||
int dist; |
int dist; |
||
int prev; |
int prev; |
||
int visited; |
int visited; |
||
int vindex; |
|||
⚫ | |||
} vertex_t; |
} vertex_t; |
||
typedef struct { |
typedef struct { |
||
vertex_t ** |
vertex_t **vertices; |
||
int |
int vertices_len; |
||
int |
int vertices_size; |
||
} graph_t; |
} graph_t; |
||
typedef struct { |
typedef struct { |
||
int *vertices; |
|||
int len; |
int len; |
||
int size; |
int size; |
||
Line 397: | Line 397: | ||
void add_vertex (graph_t *g, int i) { |
void add_vertex (graph_t *g, int i) { |
||
if (g-> |
if (g->vertices_size < i + 1) { |
||
int size = g-> |
int size = g->vertices_size * 2 > i ? g->vertices_size * 2 : i + 4; |
||
g-> |
g->vertices = realloc(g->vertices, size * sizeof (vertex_t *)); |
||
for (int j = g-> |
for (int j = g->vertices_size; j < size; j++) { |
||
g-> |
g->vertices[j] = NULL; |
||
} |
} |
||
g-> |
g->vertices_size = size; |
||
} |
} |
||
if (!g-> |
if (!g->vertices[i]) { |
||
g-> |
g->vertices[i] = calloc(1, sizeof (vertex_t)); |
||
g-> |
g->vertices_len++; |
||
⚫ | |||
} |
} |
||
} |
} |
||
Line 417: | Line 416: | ||
add_vertex(g, a); |
add_vertex(g, a); |
||
add_vertex(g, b); |
add_vertex(g, b); |
||
vertex_t *v = g-> |
vertex_t *v = g->vertices[a]; |
||
if (v-> |
if (v->edges_len >= v->edges_size) { |
||
v-> |
v->edges_size = v->edges_size ? v->edges_size * 2 : 4; |
||
v-> |
v->edges = realloc(v->edges, v->edges_size * sizeof (edge_t *)); |
||
} |
} |
||
edge_t *e = calloc(1, sizeof (edge_t)); |
edge_t *e = calloc(1, sizeof (edge_t)); |
||
e->vertex = b; |
e->vertex = b; |
||
e->weight = w; |
e->weight = w; |
||
v-> |
v->edges[v->edges_len++] = e; |
||
} |
} |
||
void |
void up_heap (heap_t *h, graph_t *g, int i) { |
||
vertex_t *v = g->vertices[i]; |
|||
int j = v->hindex; |
|||
int k = j / 2; |
|||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
} |
} |
||
h->vertices[j] = i; |
|||
⚫ | |||
} |
|||
void push_heap (heap_t *h, graph_t *g, int i) { |
|||
vertex_t *v = g->vertices[i]; |
|||
if (!v->hindex) { |
|||
if (h->len + 1 >= h->size) { |
if (h->len + 1 >= h->size) { |
||
h->size = h->size ? h->size * 2 : 4; |
h->size = h->size ? h->size * 2 : 4; |
||
h-> |
h->vertices = realloc(h->vertices, h->size * sizeof (int)); |
||
} |
} |
||
h->len++; |
h->len++; |
||
v->hindex = h->len; |
|||
} |
} |
||
up_heap(h, g, i); |
|||
⚫ | |||
⚫ | |||
h->vertex[i]->hindex = i; |
|||
i = j; |
|||
⚫ | |||
} |
|||
h->vertex[i] = v; |
|||
⚫ | |||
} |
} |
||
int min (heap_t *h, graph_t *g, int n, ...) { |
|||
va_list args; |
|||
va_start(args, n); |
|||
⚫ | |||
int m = va_arg(args, int); |
|||
⚫ | |||
⚫ | |||
j = va_arg(args, int); |
|||
if (j > h->len) |
|||
⚫ | |||
vertex_t *v = g->vertices[h->vertices[m]]; |
|||
vertex_t *u = g->vertices[h->vertices[j]]; |
|||
⚫ | |||
⚫ | |||
} |
} |
||
va_end(args); |
|||
⚫ | |||
⚫ | |||
⚫ | |||
} |
|||
⚫ | |||
void down_heap (heap_t *h, graph_t *g) { |
|||
int k = h->vertices[1]; |
|||
int i = 1; |
int i = 1; |
||
while (1) { |
while (1) { |
||
int |
int j = min(h, g, 3, i, 2 * i, 2 * i + 1); |
||
if (j == i) |
|||
⚫ | |||
⚫ | |||
⚫ | |||
if (j + 1 <= h->len && h->vertex[j + 1]->dist < h->vertex[k]->dist) { |
|||
⚫ | |||
⚫ | |||
⚫ | |||
break; |
break; |
||
h->vertices[i] = h->vertices[j]; |
|||
} |
|||
h-> |
g->vertices[h->vertices[i]]->hindex = i; |
||
i = j; |
|||
⚫ | |||
} |
} |
||
h-> |
h->vertices[i] = k; |
||
g->vertices[k]->hindex = i; |
|||
} |
|||
⚫ | |||
int pop_heap (heap_t *h, graph_t *g) { |
|||
int i = h->vertices[1]; |
|||
⚫ | |||
⚫ | |||
down_heap(h, g); |
|||
⚫ | |||
} |
} |
||
Line 485: | Line 502: | ||
a = a - 'a'; |
a = a - 'a'; |
||
b = b - 'a'; |
b = b - 'a'; |
||
for (i = 0; i < g-> |
for (i = 0; i < g->vertices_len; i++) { |
||
vertex_t *v = g-> |
vertex_t *v = g->vertices[i]; |
||
v->dist = INT_MAX; |
v->dist = INT_MAX; |
||
v->prev = 0; |
v->prev = 0; |
||
v->visited = 0; |
v->visited = 0; |
||
} |
} |
||
g-> |
vertex_t *v = g->vertices[a]; |
||
⚫ | |||
heap_t *h = calloc(1, sizeof (heap_t)); |
heap_t *h = calloc(1, sizeof (heap_t)); |
||
push_heap(h, g |
push_heap(h, g, a); |
||
while ( |
while (h->len) { |
||
i = pop_heap(h, g); |
|||
if ( |
if (i == b) |
||
break; |
break; |
||
v = g->vertices[i]; |
|||
v->visited = 1; |
v->visited = 1; |
||
for (j = 0; j < v-> |
for (j = 0; j < v->edges_len; j++) { |
||
edge_t *e = v-> |
edge_t *e = v->edges[j]; |
||
vertex_t *u = g-> |
vertex_t *u = g->vertices[e->vertex]; |
||
if (!u->visited && v->dist + e->weight <= u->dist) { |
if (!u->visited && v->dist + e->weight <= u->dist) { |
||
u->prev = |
u->prev = i; |
||
u->dist = v->dist + e->weight; |
u->dist = v->dist + e->weight; |
||
push_heap(h, |
push_heap(h, g, e->vertex); |
||
} |
} |
||
} |
} |
||
Line 512: | Line 530: | ||
} |
} |
||
void print_path (graph_t *g |
void print_path (graph_t *g, int i) { |
||
i = i - 'a'; |
|||
vertex_t *v = g-> |
vertex_t *v = g->vertices[i], *u = v; |
||
if (v->dist == INT_MAX) { |
if (v->dist == INT_MAX) { |
||
printf("no path\n"); |
printf("no path\n"); |
||
return; |
return; |
||
} |
} |
||
int j = 1, k; |
|||
while (u->dist) { |
|||
u = g->vertices[u->prev]; |
|||
} |
|||
j++; |
|||
⚫ | |||
} |
} |
||
char *a = malloc(j); |
|||
a[j - 1] = 'a' + i; |
|||
for (k = 0, u = v; k < j - 1; k++, u = g->vertices[u->prev]) { |
|||
printf("\n"); |
|||
⚫ | |||
} |
} |
||
printf("%d %.*s\n", v->dist, j, a); |
|||
} |
} |
||
Line 543: | Line 562: | ||
add_edge(g, 'e', 'f', 9); |
add_edge(g, 'e', 'f', 9); |
||
dijkstra(g, 'a', 'e'); |
dijkstra(g, 'a', 'e'); |
||
print_path(g, 'e' |
print_path(g, 'e'); |
||
return 0; |
return 0; |
||
} |
} |