一. 最短路径问题
- 对无权图来说,进行广度优先遍历的过程,其实就求出了从一个节点开始到它所有可到达节点的最短路径
- 对无权图进行广度优先遍历,最终会形成一棵生成树,称为最短路径树(相当于有权图中的最小生成树),即解决了无权图单源最短路径问题(求从一个节点到其它所有可到达节点的最短路径)
- 有权图的最短路径问题,核心思想为“松弛操作(Relaxation)”, 即判断中间经过另一个节点到达某节点是否比直接到达该节点所花费的权重更小
二. dijkstra单源最短路径法
- 前提:图中不能含有负权边 (保证某个节点的所有相邻节点中路径最短的那个相邻节点就是最短路径上的节点,因为若通过另外的相邻节点"松弛"到达该节点,所花费的路径一定更长;如上图中,0—>2 是节点0到达所有的邻节点的路径中权重最小的路径,0—>2一定是最短路径, 因为若经过节点5"松弛"到达节点2,在没有“负权边”(1—>2)的情况下,路径一定会变长)
- 时间复杂度:O(ElogV)
//dijkstra 求无负权值图最短路径 辅助数据结构:最小索引堆
public class Dijkstra <Weight extends Number & Comparable>{
private WeightGraph<Weight> graph; //待求解的图
private int s; //源点
private boolean[] isVisited; //标记节点是否被访问
private Number[] distTo; //记录每个节点到源点的路径
private Edge<Weight>[] from; // from[i]记录最短路径中, 到达i点的边是哪一条 可以用来恢复整个最短路径
public Dijkstra(WeightGraph graph, int s){
this.graph = graph;
this.s = s;
this.distTo = new Number[graph.V()];
this.from = (Edge<Weight>[]) new Edge[graph.V()];
this.isVisited = new boolean[graph.V()];
for(int i=0; i<graph.V(); i++){
distTo[i] = 0.0;
from[i] = null;
isVisited[i] = false;
}
}
//dijkstra
public void dijkstra(){
IndexMinHeap<Weight> heap = new IndexMinHeap<>(graph.V(), true);
//初始化,
distTo[s] = 0.0;
from[s] = new Edge<Weight>(s,s,(Weight)(Number) 0.0);
heap.add(s, (Weight)