最短路径
迪杰斯特拉算法
原文分析思路(理解不了这里就pass掉):在有向网中,从某一源点到其余各点都有一条最短路径。首先在这些最短路径中,长度最短的必定只有一条弧,且它的权值是从源点出发的所有弧上权的最小值;其次,第二条长度次短的最短路径只可能有两种情况:
从源点出发的一条弧,权值大于已求的最短路径的那条弧,但小于其他的从源点出发的弧的权值
是一条经过已求得最短路径的路径
该算法需要引入辅助数组D,每个分量D[i]存放当前所找到的从源点到各个终点vi的最短路径的长度。过程是:
(1)令S = {v},其中v为源点,并设定D[i] 的初始值为:D[i] = |v,vi|
(2)选择顶点vj使得:D[j] = min{D[i]}(i∈V-S),并将vj并入到S中
(3)对集合V-S的所有顶点vk,若D[j] + |vj,vk| < D[k],则修改D[k]的值
(4)重复(2)、(3)的操作共n-1次,由此求得的所有最短路径是按路径长度递增的序列
ShortestPath_DIJ
package Graph;
/**
* @description 求最短路径的问题 迪杰斯特拉 算法
* (1)令S = {v},其中v为源点,并设定D[i] 的初始值为:D[i] = |v,vi|
* (2)选择顶点vj使得:D[j] = min{D[i]}(i∈V-S),并将vj并入到S中
* (3)对集合V-S的所有顶点vk,若D[j] + |vj,vk| < D[k],则修改D[k]的值
* (4)重复(2)、(3)的操作共n-1次,由此求得的所有最短路径是按路径长度递增的序列
* @date 2015年12月31日
*/
public class ShortestPath_DIJ {
// v0到其余顶点的最短路径,若p[v][w]为true,则w是从v0到v当前求得最短路径上的顶点
private boolean[][] P;
// v0到其余顶点的最小带权长度 (是变化的,一旦发现更小的,就重新赋值,到最后就是最短路径长度了)
private int[] D;
private final static int INFINITY = Integer.MAX_VALUE;
public boolean[][] getP() {
return P;
}
public int[] getD() {
return D;
}
/**
* @description 用迪杰斯特拉算法求有向网的v0到其余顶点的最短路径p[v]及其权值D[v]
* @date 2015年12月31日
*/
public void DIJ(MGraph G, int v0){
int vexNum = G.getVexNum(); // 顶点数
this.P = new boolean[vexNum][vexNum];
this.D = new int[vexNum];
//finish[v]为true当且仅当v属于S,即已经求得从v0到v的最短路径
boolean[] finish = new boolean[vexNum];
//初始化所有数据
for(int v = 0; v < vexNum; v++){
finish[v] = false;
D[v] = G.getArcs()[v0][v];
for(int w = 0; w < vexNum; w++){
P[v][w] = false;
}
if(D[v] < INFINITY){
P[v][v0] = true;
P[v][v] = true;
}
}
D[v0] = 0; //从v0开始,并入S集
finish[v0] = true;
int v = -1 ; // 这里的赋值没有什么实际意义,只是为了保证编译正确
//开始主循环,每次求得v0到某个v顶点的最短路径,并将v加入到S集.循环n-1次
for(int i = 1; i < vexNum; i++){
int min = INFINITY; //当前所知离v0最近的距离
for(int w = 0; w < vexNum; w++){
if( !finish[w]){
if(D[w] < min){
v = w;
min = D[w];
}
}
}
finish[v] = true; //离v0最近的v并入S
//更新当前最短路径和距离
for(int w = 0; w < vexNum; w++){
if( !finish[w] && G.getArcs()[v][w] < INFINITY && (min + G.getArcs()[v][w] < D[w])){
D[w] = min + G.getArcs()[v][w];
//下面两句这么理解,现在路径是v0-v-w,所以经过了v点,那么v0到v的最小路径自然要给w,同时再加上w点(P[W][W] = true)
System.arraycopy(P[v], 0, P[w], 0, P[v].length);
P[w][w] = true;
}
}
}
}
// 测试
public static void main(String[] args) throws Exception {
Object[] vexs = { "v0", "v1", "v2", "v3", "v4", "v5" };
int[][] arcs = { { INFINITY, INFINITY, 10, INFINITY, 30, 100 },
{ INFINITY, INFINITY, 5, INFINITY, INFINITY, INFINITY },
{ INFINITY, INFINITY, INFINITY, 50,