先上代码
package wetalk;
import java.util.*;
import java.util.stream.Collectors;
public class DijkstraTest {
public static void main(String[] args) {
System.setProperty("mode", "direct");
Map<String, Map<String, Integer>> originalInfo1 = new HashMap<>();
Map<String, Integer> ad = new HashMap<>();
ad.put("B", 12);
ad.put("F", 16);
ad.put("G", 14);
originalInfo1.put("A", ad);
Map<String, Integer> bd = new HashMap<>();
bd.put("C", 10);
bd.put("F", 7);
originalInfo1.put("B", bd);
Map<String, Integer> cd = new HashMap<>();
cd.put("F", 6);
cd.put("E", 5);
cd.put("D", 3);
originalInfo1.put("C", cd);
Map<String, Integer> dd = new HashMap<>();
dd.put("E", 4);
originalInfo1.put("D", dd);
Map<String, Integer> ed = new HashMap<>();
ed.put("F", 2);
ed.put("G", 8);
originalInfo1.put("E", ed);
Map<String, Integer> fd = new HashMap<>();
fd.put("G", 9);
originalInfo1.put("F", fd);
Map<String, Integer> gd = new HashMap<>();
originalInfo1.put("G", gd);
System.setProperty("mode", "nonDirect");
dijkstra(originalInfo1, "D", "A");
dijkstra(originalInfo1, "A", "D");
Map<String, Map<String, Integer>> originalInfo2 = new HashMap<>();
Map<String, Integer> v1d = new HashMap<>();
v1d.put("v3", 10);
v1d.put("v5", 30);
v1d.put("v6", 100);
originalInfo2.put("v1", v1d);
Map<String, Integer> v2d = new HashMap<>();
v2d.put("v3", 5);
originalInfo2.put("v2", v2d);
Map<String, Integer> v3d = new HashMap<>();
v3d.put("v4", 50);
originalInfo2.put("v3", v3d);
Map<String, Integer> v4d = new HashMap<>();
v4d.put("v6", 10);
originalInfo2.put("v4", v4d);
Map<String, Integer> v5d = new HashMap<>();
v5d.put("v4", 20);
v5d.put("v6", 60);
originalInfo2.put("v5", v5d);
Map<String, Integer> v6d = new HashMap<>();
originalInfo2.put("v6", v6d);
System.setProperty("mode", "direct");
dijkstra(originalInfo2, "v1", "v6");
dijkstra(originalInfo2, "v6", "v1");
}
private static void dijkstra(Map<String, Map<String, Integer>> originalInfo, String firstNode, String lastNode) {
Map<String, String> preNodes = new HashMap<>();
Map<String, Integer> distanceInfo = new HashMap<>();
Map<String, Boolean> flags = new HashMap<>();
String mode = System.getProperty("mode", "nonDirect");
originalInfo.forEach((node, d) -> {
if (mode.equals("nonDirect")) {
d.forEach((k, v) -> originalInfo.get(k).put(node, v));
}
flags.put(node, Boolean.FALSE);
distanceInfo.put(node, Integer.MAX_VALUE);
});
distanceInfo.put(firstNode, 0);
flags.put(firstNode, Boolean.TRUE);
String nextNode = firstNode;
while (flags.values().contains(Boolean.FALSE)) {
Map<String, Integer> nearNodes = nearNodes(nextNode, flags, originalInfo);
if (nearNodes.isEmpty()) {
break;
}
String finalNextNode = nextNode;
nearNodes.forEach((node, distance) -> {
Integer curNodeMin = distanceInfo.get(finalNextNode);
int min = curNodeMin + distance;
if (min < distanceInfo.get(node)) {
distanceInfo.put(node, min);
preNodes.put(node, finalNextNode);
}
});
flags.put(nextNode, Boolean.TRUE);
nextNode = minNode(flags, distanceInfo);
}
List<String> minPath = new LinkedList<>();
String node = lastNode;
boolean canReach = true;
while (true) {
minPath.add(node);
node = preNodes.get(node);
if (node == null) {
canReach = false;
System.out.println(String.format("%s-->%s can not reach", firstNode, lastNode));
break;
}
if (node.equals(firstNode)) {
minPath.add(node);
break;
}
}
if (canReach) {
Collections.reverse(minPath);
System.out.println(String.join("-->", minPath) + " total:" + distanceInfo.get(lastNode));
}
}
private static String minNode(Map<String, Boolean> flags, Map<String, Integer> distanceInfo) {
Map<String, Integer> temp = new HashMap<>(distanceInfo);
Set<String> visitedNodes = visitedNodes(flags);
visitedNodes.forEach(visitedNode -> temp.remove(visitedNode));
if (temp.isEmpty()) {
return null;
}
Integer min = Collections.min(temp.values());
for (Map.Entry<String, Integer> entry : temp.entrySet()) {
if (entry.getValue() == min) {
return entry.getKey();
}
}
return null;
}
private static Map<String, Integer> nearNodes(String
thisNode, Map<String, Boolean> flags, Map<String, Map<String, Integer>> originalInfo) {
HashMap<String, Integer> result = new HashMap<>(originalInfo.get(thisNode));
Set<String> visitedNodes = visitedNodes(flags);
visitedNodes.forEach(visitedNode -> result.remove(visitedNode));
return result;
}
private static Set<String> visitedNodes(Map<String, Boolean> flags) {
return flags.entrySet().stream().filter(Map.Entry::getValue).map(Map.Entry::getKey).collect(Collectors.toSet());
}
}
demo1(图)
demo2(图)