java算法导论之FloydWarshall算法实现代码
摘要:算法导论之FloydWarshall算法
求一个图中任意两点之间的最短路径
FloydWarshall算法是通过动态规划来计算任意两点之间的最短路径 如果普通求最短路径,可以对图进行V次(顶点数)BellmanFord算法。这样的话时间复杂度为EV^2 如果是稀疏图,则近似于V^3 但是如果是密集图,则时间复杂度会近似达到V^4,这种情况需要优化,这里FloydWarshall通过动态规划进行优化 ,并且使用邻接矩阵来表示图。
实例代码:
packageorg.loda.graph; importjava.math.BigDecimal; importjava.math.RoundingMode; importorg.loda.util.In; /** * *@ClassName:FloydWarshall *@Description:求一个图中任意两点之间的最短路径 * *FloydWarshall算法是通过动态规划来计算任意两点之间的最短路径 * *如果普通求最短路径,可以对图进行V次(顶点数)BellmanFord算法。这样的话时间复杂度为EV^2 *如果是稀疏图,则近似于V^3 *但是如果是密集图,则时间复杂度会近似达到V^4,这种情况需要优化,这里FloydWarshall通过动态规划进行优化 *,并且使用邻接矩阵来表示图。 *d(i,j);ifm=0 *D(i,j,m)={ *min(D(i,m,m-1)+D(m,j,m-1),D(i,j,m-1));ifm!=0 *@authorminjun *@date2015年6月1日上午9:39:42 * */ publicclassFloydWarshall{ privatedouble[][]d; privateint[][]prev; privateintv; privatebooleannegativeCycle; publicFloydWarshall(intv){ this.v=v; d=newdouble[v][v]; prev=newint[v][v]; //默认设置所有节点都不可达,而自己到自己是可达并且距离为0.0 for(inti=0;ij路径中的一个中间点 for(inti=0;i d[i][k]+d[k][j]){ d[i][j]=d[i][k]+d[k][j]; prev[i][j]=k; } } } } //四舍五入距离 for(inti=0;i i的距离d[i][i],如果存在小于0的,表示这个i->i的环路的权重和形成了一个负值,也就是存在这个负权重 //在之前的其他最短路径算法中,无法通过这个方法来检测负环,因为之前路径距离都是保存在一个一维数组中,相等于只能检测d[0][0],无法检测每个d[i][i] for(inti=0;i b最短路径的距离 *@param@parama *@param@paramb *@param@return设定文件 *@returndouble返回类型 *@throws */ publicdoubledistTo(inta,intb){ if(hasNegativeCycle()) thrownewRuntimeException("有负权重环,不存在最短路径"); returnd[a][b]; } /** * *@Title:printShortestPath *@Description:打印a->b最短路径 *@param@return设定文件 *@returnIterable 返回类型 *@throws */ publicbooleanprintShortestPath(inta,intb){ if(hasNegativeCycle()){ System.out.print("有负权重环,不存在最短路径"); }elseif(a==b) System.out.println(a+"->"+b); else{ System.out.print(a+"->"); path(a,b); System.out.print(b); } returntrue; } privatevoidpath(inta,intb){ intk=prev[a][b]; if(k==-1){ return; } path(a,k); System.out.print(k+"->"); path(k,b); } /** * *@Title:addEdge *@Description:添加边 *@param@parama *@param@paramb *@param@paramw设定文件 *@returnvoid返回类型 *@throws */ publicvoidaddEdge(inta,intb,doublew){ d[a][b]=w; } publicstaticvoidmain(String[]args){ //不含负权重环的文本数据 Stringtext1="F:\\算法\\attach\\tinyEWDn.txt"; //含有负权重环的文本数据 Stringtext2="F:\\算法\\attach\\tinyEWDnc.txt"; Inin=newIn(text1); intn=in.readInt(); FloydWarshallf=newFloydWarshall(n); inte=in.readInt(); for(inti=0;i 如果采用负权重环图,则会抛出异常,提示负环并表示无最短路径
如果采用不含负环的图,则会打印如下内容(目前以s=0作测试,其他点作为原点的最短路径可以自行尝试):
0到0的距离为:0.0 0->0 0到1的距离为:0.93 0->2->7->3->6->4->5->1 0到2的距离为:0.26 0->2 0到3的距离为:0.99 0->2->7->3 0到4的距离为:0.26 0->2->7->3->6->4 0到5的距离为:0.61 0->2->7->3->6->4->5 0到6的距离为:1.51 0->2->7->3->6 0到7的距离为:0.6 0->2->7感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!