1. 最短路径的描述
给出有向图G,它的每条边都有一个非负的长度(耗费)a[i][j],路径的长度即为此路径所经过的边的长度之和。对于给定的源顶点s,需找出从它到图中其他任意顶点(称为目的)的最短路径。
2. 生成最短路径的贪心算法
利用E. Dijkstra发明的贪心算法可以解决最短路径问题,它通过分步方法求出最短路径。每一步产生一个到达新的目的顶点的最短路径。下一步所能达到的目的顶点通过如下贪心准则选取:在还未产生最短路径的顶点中,选择路径长度最短的目的顶点。也就是说, Dijkstra的方法按路径长度顺序产生最短路径。 首先最初产生从s到它自身的路径,这条路径没有边,其长度为0。在贪婪算法的每一步中,产生下一个最短路径。方法是在目前产生的每一条最短路径中,考虑加入一条最短的边,再从所有这些边中先选择最短的,这种策略即是Dijkstra算法。
procedure SHORTEST-PATHS(v,COST,DIST,n)
//G是一个n结点有向图,他由其成本领接矩阵COST(n,n)表示DIST(j)被置以节电v到节电j的最短路径长度,这里1≤j≤n。DIST(v)被置成零。//
boolean S(1:n);real COST(1:n;1:n),DIST(1:n)
integer u,v,n,num,i,w
for i 1 to n do //将集合S初始化为空//
S(i) 0;DIST(i) COST(v,i)
repeat
S(v) 1;DIST(v) 0 //结点v计入S//
for num 2 to n-1 do //确定由结点v出发的n-1条路//
选取结点u,它使得DIST(u)=
S(u) 1 //结点u计入S//
for 所有S(w)=0的结点w do //修改距离//
DIST(w) min(DIST(w),DIST(u)+COST(u,w))
repeat
repeat
end SHORTEST-PATHS
2. 问题描述
在下图的有向图中(这里用任两点间的距离矩阵表示),利用算法SHORTEST-PATHS获取按长度非降次序排列的由结点1到其余结点最短路径长度。
-1,-1,15,-1,-1,-1 //定义距离数组,-1表示不可到达
2,-1,-1,-1,10,30
-1,4,-1,-1,-1,10
-1,-1,-1,-1,-1,-1
-1,-1,-1,15,-1,-1
-1,-1,-1,4,10,-1
3. 程序清单
/**单源点最短路径问题
* ShortestPath2.java
*/
package com.algorithm.knapsack;
public class ShortestPath2 {
static int SIZE = 6;
static int INF = Integer.MAX_VALUE;
public static void dijkstra(int v,int[][] cost,int[] dist){
int n=dist.length;
//System.out.println(n);
boolean[] s=new boolean[n];
for(int i=0;i<n;i++) //dist[]数组初始化为点v到各点的初始距离
{
dist[i] = cost[v][i];
s[i] = false; //将集合s初始化为false
}
dist[v]=0;s[v]=true; //结点v计入s
for(int i=0;i<n;i++)
{
int temp = Integer.MAX_VALUE;
int u=v;
for(int j=0;j<n;j++)
if(!s[j]&&(dist[j]<temp)) //找到还没被放入到s中的点
{
u = j;
temp =dist[j];
}
s[u] = true;
for(int j=0;j<n;j++)
if(!s[j]&&(cost[u][j]<Integer.MAX_VALUE))
{
int newDistance = dist[u]+cost[u][j]; //修改距离
if(newDistance<dist[j]) //如果新的距离比原有距离短,则修改
dist[j] = newDistance;
}
}
}
public static void main(String[] args){
int dist[] = new int[SIZE];
int cost[][] = {{INF,INF,15,INF,INF,INF}, //定义距离数组,INF表示不可到达
{2,INF,INF,INF,10,30},
{INF,4,INF,INF,INF,10},
{INF,INF,INF,INF,INF,INF},
{INF,INF,INF,15,INF,INF},
{INF,INF,INF,4,10,INF}};
int v=0; //从图中的结点1开始
int[] index = new int[6];
dijkstra(v,cost,dist); //调用dijkstra方法求v到其它结点的距离
for(int i=0;i<dist.length;i++)
index[i]=i;
for(int i=0;i<dist.length-1;i++)
{
for(int j=i+1;j<dist.length;j++)
{
if(dist[i]>dist[j]) //对求得路径数组进行排序
{
int temp = dist[i];
dist[i] = dist[j];
dist[j] = temp;
int x=index[i]; //交换相应的数组下标
index[i] = index[j];
index[j] = x;
}
}
}
for(int i=1;i<6;i++)
System.out.println("从结点1到结点"+(index[i]+1)+"的最短距离是:"+dist[i]);
}
}