java算法导论之FloydWarshall算法实现代码
发布时间 - 2026-01-11 01:08:50 点击率:次摘要: 算法导论之FloydWarshall算法

求一个图中任意两点之间的最短路径
FloydWarshall算法是通过动态规划来计算任意两点之间的最短路径
如果普通求最短路径,可以对图进行V次(顶点数)BellmanFord算法。 这样的话时间复杂度为EV^2
如果是稀疏图,则近似于V^3
但是如果是密集图,则时间复杂度会近似达到V^4,这种情况需要优化,这里FloydWarshall通过动态规划进行优化
,并且使用邻接矩阵来表示图。
实例代码:
package org.loda.graph;
import java.math.BigDecimal;
import java.math.RoundingMode;
import org.loda.util.In;
/**
*
* @ClassName: FloydWarshall
* @Description: 求一个图中任意两点之间的最短路径
*
* FloydWarshall算法是通过动态规划来计算任意两点之间的最短路径
*
* 如果普通求最短路径,可以对图进行V次(顶点数)BellmanFord算法。 这样的话时间复杂度为EV^2
* 如果是稀疏图,则近似于V^3
* 但是如果是密集图,则时间复杂度会近似达到V^4,这种情况需要优化,这里FloydWarshall通过动态规划进行优化
* ,并且使用邻接矩阵来表示图。
* d(i,j); if m=0
* D(i,j,m)={
* min(D(i,m,m-1)+D(m,j,m-1),D(i,j,m-1)); if m!=0
* @author minjun
* @date 2015年6月1日 上午9:39:42
*
*/
public class FloydWarshall {
private double[][] d;
private int[][] prev;
private int v;
private boolean negativeCycle;
public FloydWarshall(int v) {
this.v = v;
d = new double[v][v];
prev = new int[v][v];
// 默认设置所有节点都不可达,而自己到自己是可达并且距离为0.0
for (int i = 0; i < v; i++) {
for (int j = 0; j < v; j++) {
d[i][j] = Double.POSITIVE_INFINITY;
prev[i][j] = -1;
if(i==j){
d[i][j] = 0;
}
}
}
}
/**
*
* @Title: findShortestPath
* @Description: 查询最短路径
* @param 设定文件
* @return void 返回类型
* @throws
*/
public void findShortestPath() {
//查找最短路径
for (int k = 0; k < v; k++) {
//将每个k值考虑成i->j路径中的一个中间点
for (int i = 0; i < v; i++) {
for (int j = 0; j < v; j++) {
//如果存在使得权重和更小的中间值k,就更新最短路径为经过k的路径
if (d[i][j] > d[i][k] + d[k][j]) {
d[i][j] = d[i][k] + d[k][j];
prev[i][j]=k;
}
}
}
}
//四舍五入距离
for (int i = 0; i < v; i++) {
for (int j = 0; j < v; j++) {
d[i][j] = new BigDecimal(d[i][j]).setScale(2,
RoundingMode.HALF_UP).doubleValue();
}
}
//检测负权重环的方式很简单,就是判断所有i->i的距离d[i][i],如果存在小于0的,表示这个i->i的环路的权重和形成了一个负值,也就是存在这个负权重
//在之前的其他最短路径算法中,无法通过这个方法来检测负环,因为之前路径距离都是保存在一个一维数组中,相等于只能检测d[0][0],无法检测每个d[i][i]
for(int i=0;i<v;i++){
if(d[i][i]<0)
negativeCycle=true;
}
}
/**
*
* @Title: hasNegativeCycle
* @Description: 是否拥有负权重环
* @param @return 设定文件
* @return boolean 返回类型
* @throws
*/
public boolean hasNegativeCycle() {
return negativeCycle;
}
/**
*
* @Title: distTo
* @Description: a->b最短路径的距离
* @param @param a
* @param @param b
* @param @return 设定文件
* @return double 返回类型
* @throws
*/
public double distTo(int a, int b) {
if (hasNegativeCycle())
throw new RuntimeException("有负权重环,不存在最短路径");
return d[a][b];
}
/**
*
* @Title: printShortestPath
* @Description: 打印a->b最短路径
* @param @return 设定文件
* @return Iterable<Integer> 返回类型
* @throws
*/
public boolean printShortestPath(int a,int b){
if (hasNegativeCycle()){
System.out.print("有负权重环,不存在最短路径");
}else if(a==b)
System.out.println(a+"->"+b);
else{
System.out.print(a+"->");
path(a,b);
System.out.print(b);
}
return true;
}
private void path(int a, int b) {
int k=prev[a][b];
if(k==-1){
return;
}
path(a,k);
System.out.print(k+"->");
path(k,b);
}
/**
*
* @Title: addEdge
* @Description: 添加边
* @param @param a
* @param @param b
* @param @param w 设定文件
* @return void 返回类型
* @throws
*/
public void addEdge(int a, int b, double w) {
d[a][b] = w;
}
public static void main(String[] args) {
// 不含负权重环的文本数据
String text1 = "F:\\算法\\attach\\tinyEWDn.txt";
// 含有负权重环的文本数据
String text2 = "F:\\算法\\attach\\tinyEWDnc.txt";
In in = new In(text1);
int n = in.readInt();
FloydWarshall f = new FloydWarshall(n);
int e = in.readInt();
for (int i = 0; i < e; i++) {
f.addEdge(in.readInt(), in.readInt(), in.readDouble());
}
f.findShortestPath();
int s = 0;
for (int i = 0; i < n; i++) {
System.out.println(s + "到" + i + "的距离为:" + f.distTo(s, i));
f.printShortestPath(s, i);
System.out.println();
}
}
}
如果采用负权重环图,则会抛出异常,提示负环并表示无最短路径
如果采用不含负环的图,则会打印如下内容(目前以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
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!
# 算法导论之FloydWarshall算法
# FloydWarshall算法
# Java算法之数组冒泡排序代码实例讲解
# Java算法之串的简单处理
# Java算法实现调整数组顺序使奇数位于偶数之前的讲解
# Java算法实现杨辉三角的讲解
# Java算法之冒泡排序实例代码
# Java算法之最长公共子序列问题(LCS)实例分析
# java算法实现红黑树完整代码示例
# Java算法之堆排序代码示例
# java算法之二分查找法的实例详解
# java算法实现预测双色球中奖号码
# Java算法之递归算法计算阶乘
# JAVA算法起步之插入排序实例
# JAVA算法起步之堆排序实例
# JAVA算法起步之快速排序实例
# 关于各种排列组合java算法实现方法
# Java算法之时间复杂度和空间复杂度的概念和计算
# 最短
# 两点
# 不存在
# 这种情况
# 可达
# 不含
# 以对
# 则会
# 图中
# 这样的话
# 都是
# 都不
# 形成了
# 希望能
# 很简单
# 在一
# 谢谢大家
# 方法来
# 抛出
# 更小
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
制作ppt免费网站有哪些,有哪些比较好的ppt模板下载网站?
Laravel中Service Container是做什么的_Laravel服务容器与依赖注入核心概念解析
开心动漫网站制作软件下载,十分开心动画为何停播?
大连 网站制作,大连天途有线官网?
rsync同步时出现rsync: failed to set times on “xxxx”: Operation not permitted
如何在阿里云服务器自主搭建网站?
什么是javascript作用域_全局和局部作用域有什么区别?
Laravel如何连接多个数据库_Laravel多数据库连接配置与切换教程
Laravel如何发送邮件和通知_Laravel邮件与通知系统发送步骤
iOS UIView常见属性方法小结
北京网页设计制作网站有哪些,继续教育自动播放怎么设置?
如何在橙子建站上传落地页?操作指南详解
Laravel队列任务超时怎么办_Laravel Queue Timeout设置详解
JS碰撞运动实现方法详解
如何打造高效商业网站?建站目的决定转化率
如何在万网开始建站?分步指南解析
重庆市网站制作公司,重庆招聘网站哪个好?
成都品牌网站制作公司,成都营业执照年报网上怎么办理?
如何在自有机房高效搭建专业网站?
🚀拖拽式CMS建站能否实现高效与个性化并存?
Android自定义控件实现温度旋转按钮效果
如何在宝塔面板中创建新站点?
Laravel如何使用Contracts(契约)进行编程_Laravel契约接口与依赖反转
教学论文网站制作软件有哪些,写论文用什么软件
?
怎样使用JSON进行数据交换_它有什么限制
JavaScript中如何操作剪贴板_ClipboardAPI怎么用
公司网站制作需要多少钱,找人做公司网站需要多少钱?
香港服务器选型指南:免备案配置与高效建站方案解析
Laravel如何使用Eloquent进行子查询
详解Nginx + Tomcat 反向代理 如何在高效的在一台服务器部署多个站点
LinuxShell函数封装方法_脚本复用设计思路【教程】
Laravel事件监听器怎么写_Laravel Event和Listener使用教程
canvas 画布在主流浏览器中的尺寸限制详细介绍
Windows11怎样设置电源计划_Windows11电源计划调整攻略【指南】
如何用PHP快速搭建CMS系统?
Laravel如何升级到最新版本?(升级指南和步骤)
android nfc常用标签读取总结
如何在香港服务器上快速搭建免备案网站?
东莞专业网站制作公司有哪些,东莞招聘网站哪个好?
如何用AI一键生成爆款短视频文案?小红书AI文案写作指令【教程】
成都网站制作公司哪家好,四川省职工服务网是做什么用?
Laravel怎么在Blade中安全地输出原始HTML内容
如何在IIS服务器上快速部署高效网站?
UC浏览器如何设置启动页 UC浏览器启动页设置方法
香港服务器网站生成指南:免费资源整合与高速稳定配置方案
如何挑选优质建站一级代理提升网站排名?
Laravel怎么使用Blade模板引擎_Laravel模板继承与Component组件复用【手册】
Laravel如何实现密码重置功能_Laravel密码找回与重置流程
如何在建站之星网店版论坛获取技术支持?
如何破解联通资金短缺导致的基站建设难题?

