RosettaCodeData/Task/Dijkstras-algorithm/D/dijkstras-algorithm.d

84 lines
2.3 KiB
D

import std.stdio, std.typecons, std.algorithm, std.container;
alias Vertex = string;
alias Weight = int;
struct Neighbor {
Vertex target;
Weight weight;
}
alias AdjacencyMap = Neighbor[][Vertex];
pure dijkstraComputePaths(Vertex source, Vertex target, AdjacencyMap adjacencyMap){
Weight[Vertex] minDistance;
Vertex[Vertex] previous;
foreach(v, neighs; adjacencyMap){
minDistance[v] = Weight.max;
foreach(n; neighs) minDistance[n.target] = Weight.max;
}
minDistance[source] = 0;
auto vertexQueue = redBlackTree(tuple(minDistance[source], source));
foreach(_, u; vertexQueue){
if (u == target)
break;
// Visit each edge exiting u.
foreach(n; adjacencyMap.get(u, null)){
const v = n.target;
const distanceThroughU = minDistance[u] + n.weight;
if(distanceThroughU < minDistance[v]){
vertexQueue.removeKey(tuple(minDistance[v], v));
minDistance[v] = distanceThroughU;
previous[v] = u;
vertexQueue.insert(tuple(minDistance[v], v));
}
}
}
return tuple(minDistance, previous);
}
pure dijkstraGetShortestPathTo(Vertex v, Vertex[Vertex] previous){
Vertex[] path = [v];
while (v in previous) {
v = previous[v];
if (v == path[$ - 1])
break;
path ~= v;
}
path.reverse();
return path;
}
void main() {
immutable arcs = [tuple("a", "b", 7),
tuple("a", "c", 9),
tuple("a", "f", 14),
tuple("b", "c", 10),
tuple("b", "d", 15),
tuple("c", "d", 11),
tuple("c", "f", 2),
tuple("d", "e", 6),
tuple("e", "f", 9)];
AdjacencyMap adj;
foreach (immutable arc; arcs) {
adj[arc[0]] ~= Neighbor(arc[1], arc[2]);
// Add this if you want an undirected graph:
//adj[arc[1]] ~= Neighbor(arc[0], arc[2]);
}
const minDist_prev = dijkstraComputePaths("a", "e", adj);
const minDistance = minDist_prev[0];
const previous = minDist_prev[1];
writeln(`Distance from "a" to "e": `, minDistance["e"]);
writeln("Path: ", dijkstraGetShortestPathTo("e", previous));
}