1.思路
定义一个集合S,如果已经找到v0到vi的最短路径,则将vi从集合U(U=V-S)中取出,放入S中,直至S包含所有顶点。
2.过程
(1)定义数组dis[n],dis[i]代表起点v0到vi的最短距离,初始化时dis[i] = matrix[v0][i](即,如果是邻接点则dis[i]就是边的长度,否则就是不可达,用MAX表示);定义boolean类型数组isInSet,isInSet[i]表示顶点vi是否在集合S中。
(2)初始化:设置源点isInSet[v0] = true,即将v0放入S中
(3)因为要将所有顶点放入S中,所以需要循环n-1次(因为源点v0已经在S中)。每次循环找出dis[k],即dis[k]在当前的dis数组中最小,将vk放入S中,然后如果v0到k距离+k到vx的距离,小于dis[vx]那么就更新dis[vx] = dis[k]+weight(k,vx)
3.代码
GrfDijkstra g = new GrfDijkstra(5);
g.init();
int source = 0;
int target = 1;
g.Dijkstra(source,target);
int[] path = g.getPath();
//在这里使用栈,保证按从起点到终点的顺序输出路径
Stack<Integer> stack = new Stack<Integer>();
stack.push(target);
//path中保存的是source到target最短路径中target的上一个邻接点
while(target!=source)
{
stack.push(path[target]);
target = path[target];
}
while(!stack.isEmpty())
{
System.out.print(stack.pop());
if(!stack.isEmpty())
System.out.print("-->");
}
class GrfDijkstra
{
private int[][] matirx;
private int total;
private boolean[] isInSet;
private int[] dis;
private int[] path;
public int[][] getMatirx() {
return matirx;
}
public void setMatirx(int[][] matirx) {
this.matirx = matirx;
}
public int getTotal() {
return total;
}
public void setTotal(int total) {
this.total = total;
}
public boolean[] getIsInSet() {
return isInSet;
}
public void setIsInSet(boolean[] isInSet) {
this.isInSet = isInSet;
}
public int[] getDis() {
return dis;
}
public void setDis(int[] dis) {
this.dis = dis;
}
public int[] getPath() {
return path;
}
public void setPath(int[] path) {
this.path = path;
}
public GrfDijkstra(int total)
{
this.total = total;
this.matirx = new int[total][total];
this.isInSet = new boolean[total];
this.dis = new int[total];
this.path = new int[total];
}
public void Dijkstra(int source,int target)
{
isInSet[source] = true;
for(int i=0; i<total; i++)
{
dis[i] = matirx[source][i];
}
for(int i=1; i<total; i++)
{
int min = 999;
int minV = -1;
for(int j=0; j<total; j++)
{
if(dis[j]<min && !isInSet[j])
{
min = dis[j];
minV = j;
}
}
isInSet[minV] = true;
dis[minV] = min;
for(int x=0; x<total; x++)
{
if(!isInSet[x] && (dis[minV]+matirx[minV][x]<dis[x]))
{
dis[x] = dis[minV]+matirx[minV][x];
//纪录最短路径的上一个顶点
path[x] = minV;
}
}
}
System.out.println(dis[target]);
}
public void init()
{
// 初始化矩阵为最大值(各节点都不连通)
for (int i = 0; i < this.total; i++)
for (int j = 0; j < this.total; j++)
matirx[i][j] = i==j?0:999;
// 手动设置有向路径
matirx[0][1] = 100;
matirx[0][2] = 30;
matirx[0][4] = 10;
matirx[2][1] = 60;
matirx[2][3] = 60;
matirx[3][1] = 10;
matirx[4][3] = 50;
}
}