Dijkstra算法
2017-12-20 22:22:55
Dijkstra算法是用来计算单源最短路径(Single-Source Shortest Paths,SSSP)的一种常用算法,该算法要求所有的权值为非负值。即从单个源点出发,到所有结点的最短路。该算法同时适用于有向图和无向图。
输入:图的邻接矩阵或者是邻接表以及源点。
输出:源点到其他各个点的最短路径。
算法实现过程:Dijkstra算法维护了一组结点集合S,从源结点s到该集合中的每个点的最短路径已经被找到。算法重复从结点集V-S中选择最短路径估计最小的结点u,将u添加到S中,同时对u的所有边进行松弛操作。
清除所有点的标号
设d[s]=0,其他d[i]=INF
循环n次{
在所有未标记结点中,选出d值最小的结点x
给结点x标记
对于从x出发的所有边(x,y),更新d[y] = min{d[y], d[x] + w(x,y)}
}
算法时间复杂度:

Java实现:
edges动态数组中保存的是边的详细信息,G中保存的只是边的编号。有了编号后再去edges中获得边的详细信息。其实就是邻接表的一种实现,这样在“遍历从x出发的所有边(x,y)更新d[y]”就可以写成“for(int i=0;i<G[u].size();i++) 执行每条边的松弛操作”。由于采用了邻接表的方式,所以使用聚合分析的时候松弛操作的执行次数是m次。这里使用的二叉堆的优先队列,每次更新都要花费logn,因此这里的消耗为mlogn。另外获取当前队首元素的时候也会消耗logn的维护时间,该项操作总共执行了n次,这里的消耗为nlogn。综上,总的时间消耗为(m+n)logn。
package dijkstra;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.PriorityQueue;
public class Dijkstra {
int n;
int m;
final Integer maxn = 20;
final int INF = 1 << 20;
// 存放各个边的信息
ArrayList<Edge> edges=new ArrayList<>();
// 存放结点i的邻接边的存放下标
ArrayList<Integer>[] G = new ArrayList[maxn];
// 标记是否访问过
boolean visited[] = new boolean[maxn];
// s到各个点的距离
int d[] = new int[maxn];
// 最短路径的上一个结点
int p[] = new int[maxn];
void init(int n) {
this.n = n;
for (int i = 0; i < n; i++) {
G[i] = new ArrayList<>();
}
edges.clear();
}
void addEdge(int from, int to, int dist) {
edges.add(new Edge(from, to, dist));
m = edges.size();
G[from].add(m - 1);
}
void dijkstra(int s) {
PriorityQueue<QueueNode> Q = new PriorityQueue<>(new Comparator<QueueNode>() {
@Override
public int compare(QueueNode o1, QueueNode o2) {
return o1.d - o2.d;
}
});
Arrays.fill(d, INF);
d[s] = 0;
Arrays.fill(visited, false);
Arrays.fill(p, -1);
Q.add(new QueueNode(0, s));
while (!Q.isEmpty()) {
QueueNode x = Q.poll();
int u = x.u;
if(visited[u]) continue;
visited[u]=true;
for (int i = 0; i < G[u].size(); i++) {
Edge e = edges.get(G[u].get(i));
if (d[e.to] > d[u] + e.dist) {
d[e.to] = d[u] + e.dist;
p[e.to]=u;
Q.add(new QueueNode(d[e.to], e.to));
}
}
}
}
void printPath(int e) {
if (p[e] != -1) {
printPath(p[e]);
}
System.out.print(e+" ");
}
public static void main(String[] args) {
Dijkstra dj=new Dijkstra();
dj.init(5);
dj.addEdge(0,1,10);
dj.addEdge(0,3,30);
dj.addEdge(0,4,100);
dj.addEdge(1,2,50);
dj.addEdge(2,4,10);
dj.addEdge(3,2,20);
dj.addEdge(3,4,60);
dj.dijkstra(0);
dj.printPath(2);
}
}
class Edge {
int from, to, dist;
Edge(int u, int v, int d) {
this.from = u;
this.to = v;
this.dist = d;
}
}
class QueueNode {
int d, u;
QueueNode(int d, int u) {
this.d = d;
this.u = u;
}
}

浙公网安备 33010602011771号