Dijkstra是解决有向赋权图单源最短路径问题的算法,是贪心算法的典型代表。
1. 在每个阶段,Dijkstra算法选择一个顶点v,它在所有unknown顶点中具有最小的dv,同时算法声明从s到v的最短路径是known的。
2. 更新dw值,若dv + c(v,w)是一个改进的值时,我们就置dw = dv + c(v,w)。
顶点Vertex的定义如下:
class Vertex{
public List adj;//邻接表
public boolean known; //是否已知
public DistType dist;
public Vertex path;
}
Dijkstra算法之后,可以用下面方法打印路径
//递归打印开始点到v的路径
void printPath(Vertex v){
if(v.path != null){
printPath(v.path);
System.out.print("to");
}
System.out.print(v);
}
Dijkstra算法的伪代码如下,意思是非常直观的:
void dijkstra(Vertex s){
//初始化
for each Vertex v{
v.dist = INFINITY;
v.known = false;
}
s.dist = 0;
for(;;){
Vertex v = smallest unknown distance vertex;//在未知顶点中选一个最小
if(v == NOT_A_VERTEX)//说明已经没有未知顶点
break;
v.known = true;
//更新相邻节点
for each Vertex w adjacent to v
if(!w.known)
if(v.dist + cvw < w.dist){
decrease(w.dist to v.dist + cvw);
w.path = v;
}
}
}
可以做学问的地方在于选取位置顶点中最小距离顶点的算法。
如果顺序扫描的话,每一步讲花费O(|V|),整个算法花费O(|V|^2)。
可以把unknown顶点放在一个优先队列里,每次执行一次deleteMin来找到最小距离顶点,在对相邻的顶点执行decreaseKey操作。这样可以得到O(|E|log|V|)的时间。