1.基本思想
迪杰斯特拉算法是从一个顶点到其余各顶点的最短路径算法,解决的是有权图中最短路径问题。迪杰斯特拉算法主要特点是从起始点开始,用一个数组int[ ]dist保存起点到其余各点的最短路径距离,采用贪心算法的策略,每次遍历到起点距离最近且未访问过的顶点的邻接节点并不断更新dist数组,直到扩展到终点为止。
2.算法步骤
- 设置数组 int[ ]dist 保存起点到其余各点的最短路径距离,设置集合 s,用于保存图中已找到最短路径的顶点,并将起点加入集合s,作为集合s的初始化。
- 遍历集合s中的所有顶点的所有出边,找出权值最小的出边,根据最短路径终点延申出的最短出边可确定一条新的最短路径的思想,该权值最小出边所连接的未在集合s中顶点a的最短路径就是该路径。
- 顶点a的最短路径已找到,将顶点a加入集合s,并更新dist数组
- 重复上述2~3步骤,直到所有顶点都在集合s中
3.图示举例
4.代码实现
class Solution {
/**
*
* @param map:图的邻接矩阵,如果两点直接不连通则对应的边的权值为{@code Integer.MAX_VALUE}
* @param n:图的顶点总数
*/
public int[] minimumEffortPath(int[][] map,int n) {
//利用小顶堆路径排序,得到当前的最短路径
PriorityQueue<int[]>queue=new PriorityQueue<int[]>
(Comparator.comparingInt(o -> o[2]));
//是否已经找到图中各顶点的最短路径
boolean[]searched=new boolean[n];
queue.add(new int[]{0,0});
//起点到图中其他各点的最短距离
int[]dist=new int[n];
//初始化起点到其他各点的最短距离是无穷大
Arrays.fill(dist,Integer.MAX_VALUE);
//假设起点的顶点索引是0,起点到起点的最短路径是0
dist[0]=0;
while (!queue.isEmpty()){
//小顶堆的根一定是最短路径
int[]peek=queue.poll();
int x=peek[0];
int d=peek[1];
//如果第二次遍历到顶点x,则跳过
if(searched[x]){
continue;
}
searched[x]=true;
for(int i=0;i<n;i++){
if(map[x][i]==Integer.MAX_VALUE){
continue;
}
int dd=map[x][i];
if(d+dd<dist[i]){
dist[i]=d+dd;
//将可能的最短路径加入小顶堆
queue.add(new int[]{i,d+dd});
}
}
}
return dist;
}
}