在一个图中,若从一个结点到另一个结点存在着路径,定义路径长度为一条路径上所经过的边的数目。图中从一个结点到另一个结点可能存在着多条路径,我们把路径长度最短的那条路径叫做最短路径,其路径长度叫做最短路径长度或最短距离.
在一个带权图中,若从一个结点到另一个结点存在着一条路径,则称该路径上所经过边的权值之和为该路径上的带权路径长度。带权图中从一个结点到另一个结点可能存在着多条路径,我们把带权路径长度值最小的那条路径也叫做最短路径,其带权路径长度也叫做最短路径长度或最短距离。
8.6.2 从一个点到其余各结点的最点路径
1 狄克斯特拉算法思想
狄克斯特拉算法是:设置两个结点的集合S和T,集合S中存放已找到最短路径的结点,集合T中存放当前还未找到最短路径的结点。初始状态时,集合S中只包含源点,设为v0,然后从集合T中选择到源点v0路径长度最短的结点u加入到集合S中,集合S中每加入一个新的结点u都要修改源点v0到集合T中剩余结点的当前最短路径长度值,集合T中各结点的新的当前最短路径长度值,为原来的当前最短路径长度值与从源点过结点u到达该结点的路径长度中的较小者。此过程不断重复,直到集合T中的结点全部加入到集合S 中为止。 下图为意示例:
8.6.3 每对结点之间的最短路径
弗洛伊德算法是:设矩阵cost用来存放带权有向图G的权值,即矩阵元素cost[i][j]中存放着下标为i的结点到下标为j的结点之间的权值,可以通过递推构造一个矩阵序列A0,A1,A2,……,AN来求每对结点之间的最短路径。初始时有,A0[i][j]=cost[i][j]。当已经求出Ak,要递推求解Ak+1时,可分两种情况来考虑:一种情况是该路径不经过下标为k+1的结点,此时该路径长度与从结点vi到结点vj的路径上所经过的结点下标不大于k的最短路径长度相同;另一种情况是该路径经过下标为k+1的结点,此时该路径可分为两段,一段是从结点vi到结点vk+1的最短路径,另一段是从结点vk+1到结点vj的最短路径,此时的最短路径长度等于这两段最短路径长度之和。这两种情况中的路径长度较小者,就是要求的从结点vi到结点vj的路径上所经过的结点下标不大于k+1的最短路径长度。
弗洛伊德算法的算法思想可用如下递推公式描述:
A0[i][j]=cost[i][j]
Ak+1[i][j]=min{Ak[i][j], Ak[i][k+1]+Ak[k+1][j]} (0≤k≤n-1)
也就是说,初始时,A0[i][j]=cost[i][j],然后进行递推,每递推一次,从结点vi到结点vj的最短路径上就多考虑了一个经过的中间结点,这样,经过n次递推后得到的An[i][j]就是考虑了经过图中所有结点情况下的从结点vi到结点vj的最短路径长度。
package cn.ls.path;
import cn.ls.graph.AdjMWGraph;
/**
* 狄克斯特拉算法实现
* 最短路径.
*/
public class Dijkstra {
static final int maxWeight = 9999;
/**
*
* @param g 矩阵图类
* @param v0 源点序号
* @param distance 用来存放从源点v0到其余各结点的最短距离数值。
* @param path 用来存放从源点v0到其余各结点的最短距离上到达目标结点的前一结点下标。
* @throws Exception
*/
public