单源最短路径算法

dijkstra单源最短路径算法


简单介绍:

  最短路径算法是图算法中的经典算法,是用于解决图中某个顶点到另外一个顶点所经过路径的花销最小(这里的花销可能是时间也可能指费用等)。dijkstra是用于解决单源最短路径的经典算法。

图的存储方式
  1. 邻接矩阵
      在邻接矩阵中,要获取某个结点的出度和入读,是通过扫描结点所在临界矩阵中的行列完成的。
  2. 邻接表
      在邻接表中,邻接点是通过扫描所在结点的链表完成的。
Dijkstra算法介绍

  Dijkstra算法通过不断的将结点加入待访问集合,和每次访问结点后,对待访问集合中的结点距离进行更新来求得最短路径。
  具体算法过程如下:
  1. 初始化边图(可以用邻接矩阵或邻接表表示)
  2. 初始化待访问集合dist(存储源点到某个点的最短路径权值)
  3. 将源点加入待访问集合
  4. 遍历待访问集合找到还没被访问的值最小的结点
  5. 不能找到的话代表所有结点都已访问完毕,结束。能找到的话,将找到的结点标记为已访问,并将该结点的邻接点都加入访问集合,再加入邻接点的过程中,判断是否要加入的邻接点已经存在,如果存在,判断是否通过当前路径到达能够得到更短的路径,可以的话,更新dist。
  6. 重复第4步

代码演示
public class Dijkstra {

    static class Edge {
        public int to;
        public int cost;
    }

    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        int n = scan.nextInt();
        int m = scan.nextInt();
        //模拟邻接表
        List[] g = new ArrayList[m];
        for (int i = 0; i < m; i++) {
            g[i] = new ArrayList<>();
        }
        //初始化边
        for (int i = 0; i < m; i++) {
            int from = scan.nextInt()-1;
            int to = scan.nextInt()-1;
            int cost = scan.nextInt();
            Edge e = new Edge();
            e.to = to;
            e.cost = cost;
            g[from].add(e);
        }
        int[] dist = new int[n];
        //用于记录经过的路径
        int[] path = new int[n];
        for (int i = 0; i < n; i++) {
            dist[i] = Integer.MAX_VALUE;
            path[i] = -1;
        }
        dist[0] = 0;
        dijkstra(g, n, dist, path);
        System.out.println(Arrays.toString(dist));
        System.out.println(Arrays.toString(path));

    }

    public static void dijkstra(List[] g, int n, int[] dist, int[] path) {
        boolean[] visited = new boolean[n];
        while(true) {
            int v = -1;
            int min = Integer.MAX_VALUE;
            for (int i = 0; i < dist.length; i++) {
                if(!visited[i]) {
                    if(dist[i] < min) {
                        min = dist[i];
                        v = i;
                    }
                }
            }
            if(v == -1) break;
            visited[v] = true;

            for (int i = 0; i < g[v].size(); i++) {
                if(!visited[g[v].get(i).to]) {
                    if(dist[g[v].get(i).to] == Integer.MAX_VALUE || dist[v] + g[v].get(i).cost < dist[g[v].get(i).to]) {
                        dist[g[v].get(i).to] = dist[v] + g[v].get(i).cost;
                        path[g[v].get(i).to] = v+1; 
                    }
                }
            }
        }
    }
}

你可能感兴趣的:(从零开始的算法学习生活)