目录
1、定义
我们生活中经常会使用地图来查找我们到达目的的路线,而我们希望每次走的都是最短路线,而我们这一节将要学习的就是在一个图中,寻找a点到b点的最短路径。
最短路径: 找到从一个顶点到达另一个顶点的成本最小的路径。
1.1、性质
这里我们使用加权有向图的模型来学习计算最短路径的方法。加权就是在两个顶点之间的边上加上权重,这样我们不仅要找到从a点到b点的路径,还要找到权值最小的那一条。
下图就是一个加权有向图:从0点到6点的最短路径就是0-->2-->7-->3-->6 ,权值之和最小等于:1.51
我们在利用加权有向图模型去求最短路径的时候,需要注意以下几点:
- 路径是有向的。
- 权重不一定等价于边的长短。
- 并不是所有点都是可达的,如果a点到b点没有可达的路径,那么就不存在最短路径,我们后面学习的算法都将建立在这个图所有点都是可达的情况下。
- 边的负权重将会是计算最短路径变得非常麻烦。
- 最短路径不一定是唯一的,可能有多条,我们只找到一条就行。
2、数据结构
这里我们的加权有向图在上一节加权无向图的基础上进行一定修改,就可以得到保存加权有向图的数据类型。
DirectedEdge类来存储边、边的权值、边的两个顶点。
EdgeWeightedDigraph 类 中有一个 数据链表,数组用来存储每个顶点,链表用来存储每个顶点指向的边。
2.1、有向边的代码
public class DirectedEdge {
private final int v; // 边的起点
private final int w; // 边的终点
private final double weight; // 边的权重
public DirectedEdge(int w, int v, double weight) {
this.w = w;
this.v = v;
this.weight = weight;
}
public int from() {
return v;
}
public int to() {
return w;
}
public double weight() {
return weight;
}
}
2.2、加权有向的图的代码
public class EdgeWeightedDigraph {
private final int V; // 顶点的数量
private int E; // 边的数量
private final Bag<DirectedEdge>[] adj; // 邻接表
public EdgeWeightedDigraph(int v) {
V = v;
adj = new Bag[v];
for (int i = 0; i < v; i++) {
adj[i] = new Bag<>();
}
}
/**
* 将边添加到 邻接表中
*/
public void addEdge(DirectedEdge edge) {
int v = edge.from();
adj[v].add(edge);
E++;
}
public int V() {
return V;
}
public int E() {
return E;
}
public Iterable<DirectedEdge> adj(int v){
return adj[v];
}
/**
* 将有向图中的所有边都存储到一个Bag中并返回
*/
public Iterable<DirectedEdge> edges(){
Bag<DirectedEdge> edges=new Bag<>();
for (int i=0;i<V;i++){
for (DirectedEdge e:adj[i]){