赞
踩
P的作用是记录已求出最短路径的顶点(以及相应的最短路径长度),而T则是记录还未求出最短路径的顶点(以及该顶点到起点V_0的距离)
参考https://blog.csdn.net/xiaoxi_hahaha/article/details/110257368中的题目:
完整代码如下:
import numpy as np inf = np.inf def dijkstra(graph, source): permanent = {source: 0} # 永久标号 temporary = {} # 临时标号 nodes = graph.keys() # 顶点集合 # 初始化 for node in nodes: if node != source: temporary[node] = inf current_node = source while temporary: # 若临时标号集合不为空,算法继续 neighbor_weight_list = graph[current_node] for n, w in neighbor_weight_list: if permanent[current_node] + w < temporary[n]: temporary[n] = permanent[current_node] + w min_key = None min_val = 1e6 for k, v in temporary.items(): if v < min_val: min_val = v min_key = k temporary.pop(min_key) permanent[min_key] = min_val current_node = min_key print(permanent) if __name__ == "__main__": # 有向图的邻接表,点:【(临界点,权值),(邻接点,权值)】 graph = { 0: [(1, 5), (2, 2)], 1: [(3, 1), (4, 6)], 2: [(3, 6), (5, 8)], 3: [(4, 1), (5, 2)], 4: [(6, 7)], 5: [(6, 3)], 6: [] } dijkstra(graph, 0)
为方便说明,做以下定义:
step1:初始化:所有元素入优先级队列,如图3
step2:
step3:
弹出队列头元素 C = 3 C=3 C=3
得到 C C C的邻居, n e i g h b o r s C = { B , D , E } neighbors_C=\{B,D,E\} neighborsC={B,D,E}
更新邻居标号,如图5
队列 [ B = 5 , D = 6 , E = 7 , F = ∞ ] [B=5,D=6,E=7,F=\infty] [B=5,D=6,E=7,F=∞]不为空。
step4:
step5:
弹出队列头元素 D D D
得到 D D D的邻居, n e i g h b o r s D = { E , F } neighbors_D=\{E,F\} neighborsD={E,F}
更新邻居标号,如图7
队列 [ E = 7 , F = 9 ] [E=7,F=9] [E=7,F=9]不为空。
step5:
step5:
注:Dijkstra算法应用优先队列的原因:每次弹出的队列的元素是有优先级的,即标号最小的优先弹出,这里也看出Dijkstra就是一种贪婪算法。
import java.util.*; public class Dijkstra { private final Graph graph; private final List<Vertex> vertices; private final int[][] edges; private Queue<Vertex> temporary; private Set<Vertex> permanent; Dijkstra(Graph graph) { this.graph = graph; this.vertices = graph.getVertices(); this.edges = graph.getEdges(); } private void init(int start) { vertices.get(start).setDistance(0); temporary = new PriorityQueue<>(Comparator.comparingInt(Vertex::getDistance)); temporary.addAll(vertices); permanent = new TreeSet<>(Comparator.comparingInt(Vertex::getDistance)) {{ add(vertices.get(start)); }}; System.out.printf("initialize: %s\n", temporary); } void search(int start) { init(start); System.out.println("dijkstra searching..."); while (!temporary.isEmpty()) { Vertex vertex = temporary.poll(); // 出队列 vertex.setMarked(true); List<Vertex> neighbors = graph.getNeighbors(vertex); updateDistance(vertex, neighbors); } System.out.println(permanent); } private void updateDistance(Vertex vertex, List<Vertex> neighbors) { for (Vertex neighbor : neighbors) { updateDistance(vertex, neighbor); } } private void updateDistance(Vertex vertex, Vertex neighbor) { int distance = edges[vertices.indexOf(vertex)][vertices.indexOf(neighbor)] + vertex.getDistance(); if (distance < neighbor.getDistance()) { temporary.remove(neighbor); neighbor.setDistance(distance); permanent.add(neighbor); temporary.add(neighbor); } } void writeAns() { System.out.println("\n initial data: "); for (int i = 0; i < edges.length; i++) { for (int j = 0; j < edges[i].length; j++) { if (edges[i][j] == Integer.MAX_VALUE) { System.out.print("M" + " "); } else { System.out.print(edges[i][j] + " "); } } System.out.println(); } } } class Graph { private List<Vertex> vertices; private int[][] edges; public Graph(String[] vertexName, int[][] adjacentList) { this.vertices = new ArrayList<>(); this.edges = adjacentList; Vertex[] vertices = new Vertex[vertexName.length]; for (int i = 0; i < vertexName.length; i++) { vertices[i] = new Vertex(vertexName[i]); } Collections.addAll(this.vertices, vertices); } public Graph() { } private Vertex getVertex(int index) { return vertices.get(index); } List<Vertex> getNeighbors(Vertex v) { List<Vertex> neighbors = new ArrayList<>(); int index = vertices.indexOf(v); for (int i = 0; i < vertices.size(); i++) { if (i == index) continue; if (edges[index][i] < Integer.MAX_VALUE) { Vertex neighbor = getVertex(i); if (!neighbor.isMarked()) neighbors.add(neighbor); } } return neighbors; } public List<Vertex> getVertices() { return vertices; } public int[][] getEdges() { return edges; } } class Vertex { private String name; private int distance; private boolean marked; Vertex(String name) { this.name = name; this.distance = Integer.MAX_VALUE; setMarked(false); } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getDistance() { return distance; } public void setDistance(int path) { this.distance = path; } public boolean isMarked() { return marked; } public void setMarked(boolean marked) { this.marked = marked; } @Override public String toString() { return name + "=" + distance; } } class Main { private final static int M = Integer.MAX_VALUE; public static void main(String[] args) { // 节点名称 String[] vertexName = new String[]{"A", "B", "C", "D", "E", "F"}; // 邻接矩阵 int[][] adjacentList = { {0, 6, 3, M, M, M}, {6, 0, 2, 5, M, M}, {3, 2, 0, 3, 4, M}, {M, 5, 3, 0, 5, 3}, {M, M, 4, 5, 0, 5}, {M, M, M, 3, 5, 0} }; Graph graph = new Graph(vertexName, adjacentList); Dijkstra dijkstra = new Dijkstra(graph); dijkstra.search(0); dijkstra.writeAns(); } }
运行结果如下:
[A=0, C=3, B=5, D=6, E=7, F=9]
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。