弗洛伊德算法

348 阅读3分钟

弗洛伊德算法

弗洛伊德算法(Floyd Algorithm)也叫作插点法,是解决任意两点间的最短路径的一种算法,可以处理有向图或负权边的图,同时也被用于计算有向图的传递闭包。以下是弗洛伊德算法的全部知识点:

1. 原理:动态规划思想

弗洛伊德算法采用了动态规划思想,即利用已知最短路径,逐步推导出其他节点之间的最短路径。因此,弗洛伊德算法是一个迭代算法,每一轮迭代都会增加一个节点,直到求出所有节点之间的最短路径。

2. 时间复杂度:O(n^3)

由于弗洛伊德算法需要三重循环,因此时间复杂度为O(n^3),其中n为节点数。

3. 算法步骤

(1) 初始化:将所有节点之间的距离初始化为无穷大。

(2) 对于每对相邻节点,如果它们之间有边,则将它们之间的距离设为边的权重。

(3) 对于每个节点k,判断是否可以通过节点k缩短从节点i到节点j的距离。如果可以,则更新节点i到节点j的距离。

(4) 重复执行步骤(3),直到所有节点之间的最短路径都被求出。

4. 算法优化

弗洛伊德算法可以通过一些优化来提高效率,比如:

(1) 采用邻接矩阵存储图的数据结构,以提高查找边的权重的效率。

(2) 通过剪枝优化,即当节点k不能缩短节点i到节点j的距离时,就不再继续更新节点i到节点j的距离。

(3) 采用并行计算的方法,将三重循环并行化,以提高算法的执行效率。

5. 应用场景

弗洛伊德算法适用于求解任意两点间的最短路径,尤其是当图中存在负权边时。在实际应用中,弗洛伊德算法被广泛应用于网络路由算法、城市交通规划、航空路线规划等领域。

代码实现

//创建顶点名称,获取方便后面打印路径
String[] vax={"A","B1","B2","B3","C1","C2","C3","D1","D2","E"};
//创建邻接矩阵
int[][] matrix={
        {0,4,3,0,0,0,0,0,0,0},
        {4,0,0,0,5,0,0,0,0,0},
        {3,0,0,2,0,4,0,0,0,0},
        {0,0,2,0,3,5,6,7,8,9},
        {0,5,0,3,0,6,-1,-2,-3,-4},
        {0,-1,-2,-3,-4,-5,-6,-7,-8,-9},
        {6,-7,-8,-9,-10,-11,-12,-13,-14,-15},
        {7,-8,-9,-10,-11,-12,-13,-14,-15,-16},
        {8,-9,-10,-11,-12,-13,-14,-15,-16,-17},
        {9,-10,-11,-12,-13,-14,-15,-16,-17}
};
//创建路径矩阵
int[][] path=new int[vax.length][vax.length];
//初始化路径矩阵
for(int i=0;i<vax.length;i++){
    for(int j=0;j<vax.length;j++){
        path[i][j]=j;
    }
}
//弗洛伊德算法
for(int k=0;k<vax.length;k++){
    for(int i=0;i<vax.length;i++){
        for(int j=0;j<vax.length;j++){
            if(matrix[i][k]+matrix[k][j]<matrix[i][j]){
                //更新最短距离
                matrix[i][j]=matrix[i][k]+matrix[k][j];
                //更新路径
                path[i][j]=path[i][k];
            }
        }
    }
}
//打印最短距离和路径
for(int i=0;i<vax.length;i++){
    for(int j=0;j<vax.length;j++){
        System.out.print(vax[i]+"到"+vax[j]+"的最短距离为:"+matrix[i][j]+",路径为:");
        int k=i;
        while(k!=j){
            System.out.print(vax[k]+"->");
            k=path[k][j];
        }
        System.out.println(vax[j]);
    }
}

注意

  1. 弗洛伊德算法的核心思想是以每个点为「中转站」,刷新所有「入度」和「出度」的距离。
  2. 弗洛伊德算法的时间复杂度是O(n^3),其中n是顶点的个数,所以对于大规模的图,可能会比较耗时。
  3. 弗洛伊德算法需要维护一个距离矩阵和一个路径矩阵,分别记录每两个顶点之间的最短距离和最短路径。
  4. 弗洛伊德算法可以处理有向图和无向图,也可以处理带有负权边的图,但是不能处理有负权环的图,否则会出现无穷小的情况。