昨日のダイクストラ法を C でやってみた。
#include
#include
#include
#define N 6
typedef struct edge {
int dest;
int cost;
} Edge;
typedef struct node {
Edge *edges[N];
int edge_num;
bool done;
int cost;
int from;
} Node;
void MakeEdge(Node *nodes[], int a, int b, int cost);
void PrintRoute(Node *nodes[], int start, int goal);
void FreeNodes(Node *nodes[]);
int main(void)
{
Node *nodes[N];
Node *start_node, *n, *n2;
Node *done_node;
Edge *e;
int i, j;
int start, goal;
// initialize graph.
for (i = 0; i < N; i++) {
nodes[i] = (Node *)malloc(sizeof(Node));
nodes[i]->done = false;
nodes[i]->cost = -1;
nodes[i]->from = -1;
nodes[i]->edge_num = 0;
for (j = 0; j < N; j++) {
nodes[i]->edges[j] = NULL;
}
}
MakeEdge(nodes, 0, 1, 2);
MakeEdge(nodes, 0, 2, 4);
MakeEdge(nodes, 0, 3, 5);
MakeEdge(nodes, 1, 2, 3);
MakeEdge(nodes, 2, 3, 2);
MakeEdge(nodes, 1, 4, 6);
MakeEdge(nodes, 2, 4, 2);
MakeEdge(nodes, 4, 5, 4);
MakeEdge(nodes, 3, 5, 6);
start = 0;
goal = 5;
start_node = nodes[start];
start_node->cost = 0;
start_node->done = true;
for (i = 0; i < start_node->edge_num; i++) {
e = start_node->edges[i];
n = nodes[e->dest];
n->cost = e->cost;
n->from = start;
}
while (true) {
done_node = NULL;
for (i = 0; i < N; i++) {
n = nodes[i];
if (n->done || n->cost < 0) {
continue;
} else {
for (j = 0; j < nodes[i]->edge_num; j++) {
e = n->edges[j];
n2 = nodes[e->dest];
if (n2->cost < 0) {
n2->cost = nodes[i]->cost + e->cost;
n2->from = i;
} else if (n->cost + e->cost < n2->cost) {
n2->cost = n->cost + e->cost;
n2->from = i;
}
}
if (done_node == NULL || n->cost < done_node->cost) {
done_node = n;
}
}
done_node->done = true;
}
if (done_node == NULL) {
break;
}
}
printf("%d\n", nodes[goal]->cost);
PrintRoute(nodes, start, goal);
FreeNodes(nodes);
return 0;
}
void MakeEdge(Node *nodes[], int a, int b, int cost)
{
Edge *e1, *e2;
e1 = (Edge *)malloc(sizeof(Edge));
e1->dest = b;
e1->cost = cost;
nodes[a]->edges[nodes[a]->edge_num] = e1;
nodes[a]->edge_num++;
e2 = (Edge *)malloc(sizeof(Edge));
e2->dest = a;
e2->cost = cost;
nodes[b]->edges[nodes[b]->edge_num] = e2;
nodes[b]->edge_num++;
return;
}
void PrintRoute(Node *nodes[], int start, int goal)
{
int route[N];
int hop = 0;
route[hop] = goal;
for (hop = 0; route[hop] != start; hop++) {
route[hop + 1] = nodes[route[hop]]->from;
}
printf("%d", route[hop--]);
for (; hop >= 0; hop--) {
printf(" -> %d", route[hop]);
}
printf("\n");
return;
}
void FreeNodes(Node *nodes[])
{
int i, j;
for (i = 0; i < N; i++) {
for (j = 0; j < nodes[i]->edge_num; j++) {
free(nodes[i]->edges[j]);
}
free(nodes[i]);
}
return;
}
takatoh@nightschool $ ./dijkstra 10 0 -> 2 -> 4 -> 5

