/// <summary> /// 松弛图g中的顶点v /// </summary> /// <param name="g"></param> /// <param name="v"></param> private void relax(EdgeDirectedWeightedDirgraph g, int v) { IEnumerator ie = g.adj(v).GetEnumerator(); while (ie.MoveNext()) { EdgeDirected e = (EdgeDirected)ie.Current; // 获取到该边的终点w int w = e.to(); // 通过松弛技术,判断从起点s到顶点w的最短路径是否需要先从顶点s到顶点v,然后再由定点v到顶点w if (this.distTo(v) + e.weight() < this.distTo(w)) { this.distToDouble[w] = this.distToDouble[v] + e.weight(); this.edgeTo[w] = e; // 判断pq中是否已经存在在顶点w,如果存在,则更新新权重,如果不存在则直接添加 if (this.pq.contains(w)) { this.pq.changeItem(w, this.distTo(w)); } else { this.pq.insert(w, distTo(w)); } } } }
/// <summary> /// 最短路径 /// </summary> private static void DijksraSPTest() { // 创建加权有向图 EdgeDirectedWeightedDirgraph graph = new EdgeDirectedWeightedDirgraph(8); graph.addEdge(new EdgeDirected(4, 5, 0.35f)); graph.addEdge(new EdgeDirected(5, 4, 0.35f)); graph.addEdge(new EdgeDirected(4, 7, 0.37f)); graph.addEdge(new EdgeDirected(5, 7, 0.28f)); graph.addEdge(new EdgeDirected(7, 5, 0.28f)); graph.addEdge(new EdgeDirected(5, 1, 0.32f)); graph.addEdge(new EdgeDirected(0, 4, 0.38f)); graph.addEdge(new EdgeDirected(0, 2, 0.26f)); graph.addEdge(new EdgeDirected(7, 3, 0.39f)); graph.addEdge(new EdgeDirected(1, 3, 0.29f)); graph.addEdge(new EdgeDirected(2, 7, 0.34f)); graph.addEdge(new EdgeDirected(6, 2, 0.40f)); graph.addEdge(new EdgeDirected(3, 6, 0.52f)); graph.addEdge(new EdgeDirected(6, 0, 0.58f)); graph.addEdge(new EdgeDirected(6, 4, 0.93f)); // 创建 DijksraSP 对象 查找最短路径 int start = 0; DijksraSP dijksra = new DijksraSP(graph, start); // 查找最短路径 0->6 int end = 6; QueueList <EdgeDirected> allEdges = dijksra.pathTo(end); // 遍历打印 if (allEdges == null) { Console.WriteLine("not path to " + end); } else { IEnumerator ie = allEdges.GetEnumerator(); while (ie.MoveNext()) { EdgeDirected e = (EdgeDirected)ie.Current; Console.WriteLine(e.from() + " -> " + e.to() + " : " + e.weight().ToString("F2")); } } }
/// <summary> /// 根据加权有向图g和顶点s创建一个计算顶点为s的最短路径树对象 /// </summary> /// <param name="g"></param> /// <param name="s"></param> public DijksraSP(EdgeDirectedWeightedDirgraph g, int s) { // 初始化 edgeTo this.edgeTo = new EdgeDirected[g.countV()]; // 初始化 distToDouble this.distToDouble = new double[g.countV()]; for (int i = 0; i < this.distToDouble.Length; i++) { this.distToDouble[i] = Double.PositiveInfinity; } // 初始化 pq this.pq = new IndexMinPriorityQueue <double>(g.countV()); // 找到图g中顶点s为起点的最短路径树 // 默认让顶点s进入到最短路径树中 this.distToDouble[s] = 0.0f; this.pq.insert(s, 0.0f); // 遍历pq while (!this.pq.isEmpty()) { relax(g, this.pq.delMinIndex()); } }