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]); } }
谢谢!