Dijkstra算法

一、问题描述

解决最短路径问题。

  • 对于内网图而言(边带权值),最短路径是指两顶点之间经过的边上权值之和最小的路径。

  • 对于非内网图而言(边不带权值),最短路径就是经过的边数和最小的路径。

路径中,第一个顶点为源点,最后一个顶点为终点。所求得是源点到终点的最短路径。

 

二、Dijkstra算法思想

图可以表示为,G(V, E),V为各个顶点,E为各个顶点所连的边,W为各个边的权值。

记顶点为V0,目标点为Vj,Vk为V0到Vj中间任意一点。

  • 每次遍历开始都可以确定目前与V0连接的最短路径
  • 与V0直连的点未必就是最短路径,除非与V0直连的点距离最短,可以简单证明。
  • 若与V0直连的点Vi不是最短路径,那么其只可能被最短路径更新成更短的路径。D(Vi) = Min(D(Vi), D(VK) + W(VK, Vi)),其中VK为目前的最短路径的顶点。
  • 最短路径已经是不可能再变的了,因为其它路径都比它长,所以不可能以其它路径当成中间点。

因此思想就可以总结出来了:每次都选择最短路径的顶点为中间点,去更新其它顶点上的权值。贪心思想。

 

三、Code

package algorithm;

// 设点数为v,s为源点,t为终点
// 循环v-1次,每次加入一个点,该点为 delta(s,k)
// 每次循环对上一次最小的 V-S 集合中的 k,进行松弛操作

public class Dijkstra {
    private static int M = 0x7ffffff;

    public int [] dijkstra(int [][] weight, int source){
        int vertexNum = weight.length;
        boolean [] visited = new boolean[vertexNum];
        int [] distance = new int[vertexNum];
        if(vertexNum == 0) return distance;
        for(int i = 0; i < vertexNum; i++) distance[i] = M;
        distance[source] = 0;

        //vertexNum-1 relax. find all vertexes. must find source
        for(int i = 0; i < vertexNum; i++){
            //find min.
            int min = M, k = 0;
            for(int j = 0; j< vertexNum; j++){
                if(!visited[j] && min > distance[j]){
                    min = distance[j];
                    k = j;
                }
            }
            if(min == M) break;
            relax(distance, weight, k);
            visited[k] = true;
        }
        return distance;
    }

    public void relax(int [] distance, int [][] weight, int k){
        for(int i = 0; i < distance.length; i++) distance[i] = Math.min(distance[i], distance[k] + weight[k][i]);
    }

}

 

posted @ 2019-02-12 15:28  ylxn  阅读(257)  评论(0编辑  收藏  举报