#include <iostream> #include <list> #include <map> #include <vector> #include <string> #include <set> using namespace std; typedef int vertex_t; typedef double weight_t; struct edge { vertex_t target; weight_t weight; edge( vertex_t v, weight_t w):target(v),weight(w){} }; //Definition of the edge structure. template <typename T1, typename T2> struct comparator { bool operator()( pair<T1, T2> p1, pair<T1, T2> p2) { return p1.first < p2.first; } }; //The comparator used for sorting the edge weights. typedef map<vertex_t, list<edge>> adjacentList; //The adjacent list representation of the undirected weighted graph. typedef map<vertex_t, weight_t> minDistance; //Store the minimum distances from source to each target vertex. typedef map<vertex_t, vertex_t> previousVertex; //Store the previous vertex of the current vertex that by travelling through gives the munimum distance to the source. typedef set<pair<weight_t, vertex_t>, comparator<weight_t, vertex_t>> sortedEdges; //The edges are sorted for the Dijkstra algorithm by using a STL set container with self-defined comparator. void DijkstraShortestPath(vertex_t source, adjacentList & graph, minDistance & distances, previousVertex & previous); //Function for calculating the shortest distance to the source for each vertex and storing the previous vertex in the shortest path. void PrintShortestPaths(vector<string> & places, adjacentList & graph, minDistance & distances, previousVertex & previous); int main(int argc, const char* agrv[]) { adjacentList graph; vector<string> vertexNames; vertexNames.push_back("Harrisburg"); // 0 vertexNames.push_back("Baltimore"); // 1 vertexNames.push_back("Washington"); // 2 vertexNames.push_back("Philadelphia"); // 3 vertexNames.push_back("Binghamton"); // 4 vertexNames.push_back("Allentown"); // 5 vertexNames.push_back("New York"); // 6 graph[0].push_back(edge(1, 79.83)); graph[0].push_back(edge(5, 81.15)); graph[1].push_back(edge(0, 79.75)); graph[1].push_back(edge(2, 39.42)); graph[1].push_back(edge(3, 103.00)); graph[2].push_back(edge(1, 38.65)); graph[3].push_back(edge(1, 102.53)); graph[3].push_back(edge(5, 61.44)); graph[3].push_back(edge(6, 96.79)); graph[4].push_back(edge(5, 133.04)); graph[5].push_back(edge(0, 81.77)); graph[5].push_back(edge(3, 62.05)); graph[5].push_back(edge(4, 134.47)); graph[5].push_back(edge(6, 91.63)); graph[6].push_back(edge(3, 97.24)); graph[6].push_back(edge(5, 87.94)); minDistance distances; previousVertex previousVertices; DijkstraShortestPath(0, graph, distances, previousVertices); PrintShortestPaths(vertexNames, graph, distances, previousVertices); return 0; } void DijkstraShortestPath(vertex_t source, adjacentList & graph, minDistance & distances, previousVertex & previous) { //Initialize the distances of all the target vertices to the source to a positive infinite. for(auto iter: graph) distances[iter.first] = numeric_limits<weight_t>::infinity(); distances[source] = 0; sortedEdges edgeSet; //Use STL set to overcome duplicates of the (distance, target) pairs. for(auto iter: graph) { pair<weight_t, vertex_t> wrapper(distances[iter.first], iter.first); edgeSet.insert(wrapper); } while(!edgeSet.empty()) { vertex_t current = edgeSet.begin()->second; edgeSet.erase(edgeSet.begin()); //Visiting each vertex connecting to "current". At beginning, "current" is the source vertex based on the graph initialization procedure in the main() function. for(auto iter: graph[current]) { vertex_t neighbor = iter.target; weight_t weightToNeighbor = iter.weight; //Core of the Dijkstra Shortest Paht algorithm. weight_t distanceThroughCurrent = distances[current] + weightToNeighbor; if(distanceThroughCurrent < distances[neighbor]) { //Remove the (distance, target) pair from the set, and readd it to the set later on, to let set perform its sorting procedure. pair<weight_t, vertex_t> wrapper(distances[neighbor], neighbor); edgeSet.erase(wrapper); distances[neighbor] = distanceThroughCurrent; previous[neighbor] = current; //Readd. wrapper.first = distances[neighbor]; edgeSet.insert(wrapper); } } } return; } void PrintShortestPaths(vector<string> & places, adjacentList & graph, minDistance & distances, previousVertex & previous) { for(auto iter: graph) { cout << "Distance to " << places[iter.first] << ": " << distances[iter.first] << endl; list<vertex_t> path; path.push_front(iter.first); previousVertex::iterator prev; vertex_t current = iter.first; while((prev = previous.find(current)) != previous.end()) { current = prev->second; path.push_front(current); } cout << "Path is: "; list<vertex_t>::iterator iterPath = path.begin(); cout << places[*iterPath++]; for(;iterPath != path.end(); iterPath++) cout << " -> " << places[*iterPath]; cout << endl << endl; } return; }
结果: