最短路径(迪杰斯特拉、弗洛伊德含代码)

用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。对于⽆向图⽽⾔,最短路径就是从源点V0到终点Vn所包含的边最少的路径

迪杰斯特拉算法

从一个顶点到其余各顶点的最短路径算法,解决的是有权图中最短路径问题。迪杰斯特拉算法主要特点是从起始点开始,采用贪心算法的策略,每次遍历到始点距离最近且未访问过的顶点的邻接节点,直到扩展到终点为止。

假设图G{V,E},集合S为已经求出的当前距离顶点V0最短的顶点的集合,那么V-S就是待计算的顶点集合,定义数组d[]中保存顶点到各顶点的当前最短路径

基本思想如下:

  1. 令S={V0}
  2. 令d[i]=data[V0][i],也就是初始V0到其他点的距离
  3. 从V-S中选取一个d[]值最小的点v,把顶点加入到集合S中,再对集合V-S中的顶点i令d[i]=min{d[i],data[v][i]}
  4. 重复步骤3,直到S=V
public class Dijkstra {
    //存储最短路径下标数组
    int[] path;
    //存储当前最短路径的权值和
    int[] shortest;
    //存储顶点是否在集合S中
    int[] isExist;

    public Dijkstra(MGraph mGraph) {
        path = new int[mGraph.vNums];
        shortest = new int[mGraph.vNums];
        isExist = new int[mGraph.vNums];
    }

    public void dijkstra(MGraph mGraph,int V0){
        //初始化数组
        for (int i = 0; i < mGraph.vNums; i++) {
            path[i] = 0;
            isExist[i] = 0;
            shortest[i] = mGraph.arcs[V0][i];
        }
        isExist[V0] = 1;//将V0加入集合S
        int k = 0;//d[]最小的点
        int min = Integer.MAX_VALUE;
        //开始循环,每次求得V0到每个结点的最短路径和
        for (int i = 1; i < mGraph.vNums; i++) {
            //从V-S中选取一个d[]值最小的点v
            for (int j = 0; j < mGraph.vNums; j++) {
                min = Integer.MAX_VALUE;
                if(isExist[j] == 0 && shortest[j] < min){
                    min = shortest[j];
                    k = j;
                }
            }
            isExist[k] = 1;//将d[]最小的点加入集合S中
            //更新当前最短路径权值和
            for (int j = 0; j < mGraph.vNums; j++) {
                if(isExist[j] == 0 && (shortest[j] < min + mGraph.arcs[k][j])){
                    shortest[j] = min + mGraph.arcs[k][j];
                    path[j] = k;
                }
            }
        }
    }
}

 

弗洛伊德算法

是一种利用动态规划的思想寻找给定的有权图中多源点之间的最短路径的算法,与迪杰斯特拉类似。

单源最短路径的迪杰斯特拉算法需要辅助数组d[],同样多源最短路径弗洛伊德算法也需要辅助二维数组D[][]

基本思想就是递归的产生矩阵A0 A1...An,矩阵Ak[i][j]表示从顶点i到顶点j以不大于下标k的顶点为途径点的最短路径长度,An-1就是最终结果

令A-1[i][j]=data[i][j],表示从顶点i到顶点j且中间不经过任何顶点的最短路径长度,也就是最原始的直线距离。

然后在所有的路径中增加中间顶点V0,如果得到的的新路径长度小于原来的路径长度,那么就以新的路径长度替换原来的路径长度。也就是对每一个矩阵元素A0[i][j] = min{A-1[i][j] =,A-1[i][0]+A0[0][j]}

依此再添加V1、V1....Vn,最后得到的矩阵就是运算结果

public class Floyd {
    //存储最短路径下标
    int[][] path;
    //最短路径权值和
    int[][] shortest;

    public Floyd(MGraph mGraph) {
        path = new int[mGraph.vNums][mGraph.vNums];
        shortest = new int[mGraph.vNums][mGraph.vNums];
    }

    public void floyd(MGraph mGraph){
        //初始化
        for (int i = 0; i < mGraph.vNums; i++) {
            for (int j = 0; j < mGraph.vNums; j++) {
                shortest[i][j] = mGraph.arcs[i][j];
                path[i][j] = j;
            }
        }
        for(int i =0;i<mGraph.vNums;i++){
            for (int j = 0; j < mGraph.vNums; j++) {
                for (int k = 0; k < mGraph.vNums; k++) {
                    if(shortest[j][k]<shortest[j][i]+shortest[i][k]){
                        shortest[j][k] = shortest[j][i]+shortest[i][k];
                        path[j][k] = k;
                    }
                }
            }
        }
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值