Dijkstra Shortest Path

#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;
}

结果:


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值