1.算法思想:
Dijsktra:确定一个起始点,找出该点到图中其余所有点路程的最小值,要求图中累加和为负数的环,可以有权值为负数的边
假设一个图如下,A为起始点:
D
9/ | \19
/ 7| \
A--- C ---E
\15 | 14/
3 \ 2| /200
B
算法:
1. 初始化一个表格(~表示无穷大):
A B C D E
A 0 ~ ~ ~ ~
2. 找出此时最小值对应的点为中转点(锁定点除外),选择A且锁定该点不再修改表格中A对应的值
3. A经过A点可以得到AA+AD=AD,AA+AC=AC,AA+AB=AB,将得到的距离和原表格中的值去较小值更新表格:
A B C D E
A 0 3 15 9 ~
4. 找出此时最小值对应的点为中转点(锁定点除外),选择B且锁定该点不再修改表格中B对应的值
5. A经过B点可以得到AB+BC=AC,AB+BE=AE,将得到的距离和原表格中的值去较小值更新表格:
A B C D E
A 0 3 5 9 203
6. 找出此时最小值对应的点为中转点(锁定点除外),选择C且锁定该点不再修改表格中C对应的值
7. A经过C点可以得到AC+CE=AE,AC+CD=AD,将得到的距离和原表格中的值去较小值更新表格:
A B C D E
A 0 3 5 9 29
8. 找出此时最小值对应的点为中转点(锁定点除外),选择D且锁定该点不再修改表格中D对应的值
9. A经过D点可以得到AD+DE=AE,将得到的距离和原表格中的值去较小值更新表格:
A B C D E
A 0 3 5 9 28
2.代码实现:
public class Dijsktra {
public static HashMap<Node, Integer> dijsktra(Node head) {
HashMap<Node, Integer> distanceMap = new HashMap<>();
distanceMap.put(head, 0);
HashSet<Node> selectedNodes = new HashSet<>();
Node minNode = getMinDistanceAndUnselectedNode(distanceMap, selectedNodes);
while (minNode != null) {
int distance = distanceMap.get(minNode);
for (Edge edge : minNode.edges) {
Node toNode = edge.to;
if (!distanceMap.containsKey(toNode)) {
distanceMap.put(toNode, distance + edge.weight);
} else {
distanceMap.put(toNode, Math.min(distanceMap.get(toNode), distance + edge.weight));
}
}
selectedNodes.add(minNode);
minNode = getMinDistanceAndUnselectedNode(distanceMap, selectedNodes);
}
return distanceMap;
}
public static Node getMinDistanceAndUnselectedNode(
HashMap<Node, Integer> distanceMap,
HashSet<Node> touchNodes) {
Node minNode = null;
int minDistance = Integer.MAX_VALUE;
for (Entry<Node, Integer> entry : distanceMap.entrySet()) {
Node node = entry.getKey();
int distance = entry.getValue();
if (distance < minDistance && !touchNodes.contains(node)) {
minNode = node;
minDistance = distance;
}
}
return minNode;
}
}