/// <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> /// 向加权有向图中添加一条边e /// </summary> /// <param name="e"></param> public void addEdge(EdgeDirected e) { // 边e是有方向的,所以只需要让e出现在起点的邻接表中即可 int v = e.from(); this.adjQueue[v].enqueue(e); this.E++; }
/// <summary> /// 获取加权有向图的所有边 /// </summary> /// <returns></returns> public QueueList <EdgeDirected> edges() { // 遍历图中的每一个顶点,得到该顶点的邻阶表遍历得到每一条边,添加到队列中返回即可 QueueList <EdgeDirected> allEdges = new QueueList <EdgeDirected>(); for (int v = 0; v < this.V; v++) { IEnumerator ie = this.adjQueue[v].GetEnumerator(); while (ie.MoveNext()) { EdgeDirected e = (EdgeDirected)ie.Current; allEdges.enqueue(e); } } return(allEdges); }
/// <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> /// 查询从起点s到顶点v的最短路径中所有的边 /// </summary> /// <param name="v"></param> /// <returns></returns> public QueueList <EdgeDirected> pathTo(int v) { // 判断从顶点 s 到顶点v是否可达 if (!this.hasPathTo(v)) { return(null); } // 创建队列对象 QueueList <EdgeDirected> allEdges = new QueueList <EdgeDirected>(); while (true) { EdgeDirected e = this.edgeTo[v]; if (e == null) { break; } allEdges.enqueue(e); v = e.from(); } return(allEdges); }