// 返回节点 from 到节点 to 之间的边的权重 int weight(int from, int to); // 输入节点 s 返回 s 的相邻节点 List<Integer> adj(int s); // 输入一幅图和一个起点 start,计算 start 到其他节点的最短距离 int[] dijkstra(int start, List<Integer>[] graph) { // 图中节点的个数 int V = graph.length; // 记录最短路径的权重,你可以理解为 dp table // 定义:distTo[i] 的值就是节点 start 到达节点 i 的最短路径权重 int[] distTo = new int[V]; // 求最小值,所以 dp table 初始化为正无穷 Arrays.fill(distTo, Integer.MAX_VALUE); // base case,start 到 start 的最短距离就是 0 distTo[start] = 0; // 优先级队列,distFromStart 较小的排在前面 Queue<State> pq = new PriorityQueue<>((a, b) -> { return a.distFromStart - b.distFromStart; }); // 从起点 start 开始进行 BFS pq.offer(new State(start, 0)); while (!pq.isEmpty()) { State curState = pq.poll(); int curNodeID = curState.id; int curDistFromStart = curState.distFromStart; //队列中有节点ID相同,但是权重不同的重复节点。 if (curDistFromStart > distTo[curNodeID]) { // 已经有一条更短的路径到达 curNode 节点了 !!!这里产生的原因,我认为是在队列中不断加元素的时候,会有重复的元素添加进来,因为当前节点的来源可能是上一层节点加进来的,然后当层节点又有路径通向当前节点,所以需要通过dp判断,当前节点是否需要处理,因为要保证路径最短,如果当前通过当前节点的路径不是最短那也就不用处理了 continue; } // 将 curNode 的相邻节点装入队列 for (int nextNodeID : adj(curNodeID)) { // 看看从 curNode 达到 nextNode 的距离是否会更短 int distToNextNode = distTo[curNodeID] + weight(curNodeID, nextNodeID); if (distTo[nextNodeID] > distToNextNode) { //针对下一节点,如果通过当前节点的路径比通过之前路径的短就进行更新 // 更新 dp table distTo[nextNodeID] = distToNextNode; // 将这个节点以及距离放入队列 pq.offer(new State(nextNodeID, distToNextNode)); } } } return distTo; }
Dijkstra
最新推荐文章于 2022-11-22 21:53:23 发布