具体的原理网上有太多了,我就不过多的赘述,具体原理请点击
关键是要利用优先队列的性质,找出剩余未标记节点的最小距离节点来进下一步。因为已标记的节点可以看做是一个整体,其他节点到这个整体的最小值节点也就是所求的下一个最短路径节点。
举例:当前网络整体为{w}
点a 到 w 距离为 1
点b 到 w 距离为 2
如果只有这两个点可以到w, 毫无疑问,a就是下一个最短路径节点。因为无论如何其他节点要么经过a,要么经过b到达w。
public class dijkstra {
int MAX = 100000;
class Node {
//定义结构体
public int to_index; //该节点的标号
public int distance; //该节点距离起点的距离 主要用来排序 不访问
Node(int x, int y){
this.to_index = x;
this.distance = y;
}
}
/*
两个集合S和U。S的作用是记录已求出最短路径的顶点(以及相应的最短路径长度)
而U则是记录还未求出最短路径的顶点(以及该顶点到起点s的距离)。
*/
public int[] getMinDistance(int[][] matrix){
boolean[] visited = new boolean[matrix.length];
// ans中visited[i] == true的全部i项组合即为S集合
// visited[i] == false的全部i项组合即为U集合
int[] ans = Arrays.copyOfRange(matrix[0],0,matrix[0].length);
//
PriorityQueue<Node> queue = new PriorityQueue<>(new Comparator<Node>() {
@Override
public int compare(Node o1, Node o2) {
return o1.distance - o2.distance;
}
});
queue.offer(new Node(0,0));
while (!queue.isEmpty()){
Node node = queue.poll();
//节点已访问则进入下一步 未访问则标记 标记过后 不会再更新该节点的距离
if (visited[node.to_index]) continue;
visited[node.to_index] = true;
int curr = node.to_index;
for (int i = 0;i< matrix.length;i++){
if (!visited[i] && matrix[curr][i] != MAX){
// 更新未访问节点到起点的距离
ans[i] = Math.min(ans[i], ans[curr] + matrix[curr][i]);
// 将该节点加入优先队列
queue.offer(new Node(i, ans[i]));
}
}
}
return ans;
}
@Test
public void test() {
int[][] weight={
{MAX,1,12,MAX,MAX,MAX},
{MAX,MAX,9,3,MAX,MAX},
{MAX,MAX,0,MAX,5,MAX},
{MAX,MAX,4,MAX,13,15},
{MAX,MAX,MAX,MAX,MAX,4},
{MAX,MAX,MAX,MAX,MAX,MAX}
};// MAX代表不可达 在应用中根据题目的范围进行大小的调整,也可以用List储存
System.out.println(Arrays.toString(getMinDistance(weight)));
}
}