当图中所有边的权重为非负值时,我们可以选用巧妙Dijkstra算法。
本文使用C++实现了这一基本算法。参考《算法导论》第24.3节。
不过在算法的实现中,取当前与原点s最近的节点操作时,采用了线性扫描的策略。如果换用堆或者优先级队列会好很多。
/** * Dijkstra‘s Single Source Shortest Path Algorithm in C++ * Time Cost : O(N^2) * Thanks to Introduction to Algorithms (CLRS) Chapter 24.3 * Author: Zheng Chen / Arclabs001 * Copyright 2015 Xi‘an University of Posts & Telecommunications */ #include <iostream> #include <vector> #include <stack> #include <fstream> #define INF 0xfffffff using namespace std; const int N = 5; const int M = 10; ifstream in; enum status {UNSELECTED,SELECTED}; struct edge { int dest; int weight; }; struct vertex { int num; int dist; int inDegree,outDegree; status _stat; vertex * parent; }V[N]; vector<edge> AdjList[N]; vector<int> SELECTED_vertex; void initialize(int s) { for(int i=0; i<N; i++) { V[i].num = i; V[i].dist = INF; V[i].parent = nullptr; V[i].inDegree = 0; V[i].outDegree = 0; V[i]._stat = UNSELECTED; AdjList[i].clear(); } for(int i=0; i<M; i++) //Read informations of edges and insert into the Adjacent List { int _start, _dest, _weight; edge * tmp = new edge; in>>_start>>_dest>>_weight; tmp->dest = _dest; tmp->weight = _weight; V[_start].outDegree++; V[_dest].inDegree++; AdjList[_start].push_back(*tmp); } V[s].dist = 0; SELECTED_vertex.clear(); } void relax(int u, int v, int weight) //The "relax" operation { if(V[v].dist > V[u].dist + weight) { V[v].dist = V[u].dist + weight; V[v].parent = &V[u]; } } void print_path(vertex *s, vertex *v) { if(v == s) cout<<s->num; else if(v->parent == nullptr) cout<<"No path from "<<s->num<<" to "<<v->num<<endl; else { print_path(s,v->parent); cout<<"->"<<v->num; } } //Get the nearest vertex to the set of selected vertices //Actually, this linear scan costed so much than I expected. //Using a heap can make the time cost better int get_nearest_vertex() { int _dist = INF; int nearest; for(int i=0;i<N;i++) { if(V[i].dist < _dist && V[i]._stat == UNSELECTED) { _dist = V[i].dist; nearest = i; } } return nearest; } void Dijkstra(int s) //The main function of Dijkstra algorithm { initialize(s); int numof_UNSELECTED = N-1; while(numof_UNSELECTED != 0) { int u = get_nearest_vertex(); SELECTED_vertex.push_back(u); edge tmp; for(int j=0; j<V[u].outDegree; j++) { tmp = AdjList[u][j]; relax(u,tmp.dest,tmp.weight); } V[u]._stat = SELECTED; numof_UNSELECTED--; } } int main() { in.open("Dijkstra.txt"); int s = 0; Dijkstra(s); cout<<"Succeed ! The distance of each vertex are :"<<endl; for(int i=0; i<N; i++) if(V[i].dist == INF) cout<<"INF "; else cout<<V[i].dist<<" "; cout<<endl<<"One of the shortest path is :"<<endl; print_path(&V[0],&V[4]); return 0; } /* Pseudo Code : Dijkstra(G,w,s) S = empty set Q = G.V - s while Q != empty set u = EXTRACT-MIN(Q) S = S ∪ u for each vertex v in AdjList[u] relax(u,v,w) */
//Dijkstra.txt文件内容如下:
0 1 10
0 3 5
1 2 1
1 3 2
2 4 4
3 1 3
3 2 9
3 4 2
4 0 7
4 2 6
每一行的三个元素分别表示某条边的起始节点、终止节点、这条边的权重。
时间: 2024-10-16 19:43:13