单源最短路径中的Dijkstra算法属于贪心算法,它的图中不允许出现权重为负值的边。
算法解决的是带权重的有向图中单源最短路径问题。
算法时间复杂度与所用的优先队列的实现有关。算法与图的深度优先遍历(DFS)和最小生成树的Prim算法相似,尤其与Prim相似。
详细介绍可看《算法导论》第24章,下面的链接是别人的介绍与C代码
别人的介绍与C代码
Java代码如下,图是由邻接链表实现的
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.PriorityQueue;
public class Test {
public static void main(String[] args) {
//构建有向图
Map<V, List<V>> G = new HashMap<>();
V s = new V('s');
V t = new V('t');
V y = new V('y');
V x = new V('x');
V z = new V('z');
List<V> sN = new LinkedList<>(); sN.add(t);sN.add(y);
List<V> tN = new LinkedList<>(); tN.add(x);tN.add(y);
List<V> yN = new LinkedList<>(); yN.add(t);yN.add(x);yN.add(z);
List<V> xN = new LinkedList<>(); xN.add(z);
List<V> zN = new LinkedList<>(); zN.add(s);zN.add(x);
G.put(s, sN);
G.put(t, tN);
G.put(x, xN);
G.put(y, yN);
G.put(z, zN);
//储存所有边的集合
List<Edge> alledges = new ArrayList<>();
alledges.add(new Edge(s, t, 10));
alledges.add(new Edge(s, y, 5));
alledges.add(new Edge(t, x, 1));
alledges.add(new Edge(t, y, 2));
alledges.add(new Edge(x, z, 4));
alledges.add(new Edge(y, t, 3));
alledges.add(new Edge(y, x, 9));
alledges.add(new Edge(y, z, 2));
alledges.add(new Edge(z, s, 7));
alledges.add(new Edge(z, x, 6));
DijkstraSPath(G, alledges,s);
}
public static void DijkstraSPath(Map<V, List<V>> G, List<Edge> alledges, V s) {
s.d = 0;//源点到自己的距离为0
PriorityQueue<V> Q = new PriorityQueue<>((v1, v2)-> {return v1.d - v2.d;});//要给优先队列传比较器
Q.addAll(G.keySet());
while(!(Q.isEmpty())) {
V u = Q.poll();//取出当前离源点最近的点
for(V v : G.get(u)) {//更新所有邻点的值
int w = Integer.MAX_VALUE;
for(Edge edge : alledges)
if((edge.s.equals(u) && edge.d.equals(v))||(edge.d.equals(u) && edge.s.equals(v)))
w = edge.w;
if(v.d > u.d + w) {
v.d = u.d + w;
Q.remove(v);//优先队列自己无法更新,要变动它才会
Q.add(v);
v.p = u;
}
}
}
for(V key : G.keySet())
System.out.println("经过DijkstraSPath算法后," + key + "距s节点的距离为" + key.d);
}
}
//结点类
class V {
char name;//结点名
int d;//记录该点到源点的路径,初始值为无限大
V p;//父节点,即算法中到这个点的最短路径的上一个点
public V(char name) {
this.name = name;
d = Integer.MAX_VALUE;
p = null;
}
public int hashCode() {//hashmap必须重写
return name;
}
public boolean equals(Object o) {//hashmap必须重写
if(!(o instanceof V))
return false;
if(o == this)
return true;
return name == ((V)o).name;
}
public String toString() {
return "" + name;
}
}
//边类
class Edge {
V s;//s与d代表边的2个端点
V d;
int w;//边的权重
public Edge(V s, V d, int w) {
this.w = w;
this.s = s;
this.d = d;
}
public String toString() {
return s + "-" + d + " " + w;
}
}