您的位置:首页 > 编程语言 > C语言/C++

图论中最短路径问题C++实现

2016-12-10 18:59 661 查看
City.h文件
#ifndef _CITY_H_
#define _CITY_H_

using namespace std;

class City {

public:

// 城镇的名称
string name;

// 簿记信息
bool    visited;
int total_fee;
int total_distance;
string from_city;

//默认构造函数
City() : name(""), visited(false), total_fee(0),

total_distance(0), from_city("") {}

City(string const &s): name(s), visited(false),
total_fee(0), total_distance(0), from_city("") {}
};

#endif

Road.h文件
#ifndef _ROAD_H_
#define _ROAD_H_

#include <string>

using namespace std;

class Road {

public:

int fee;
int distance;
string destination;

Road(string city, int f, int d) : fee(f),
distance(d), destination(city) {}
}
;

#endif
RoadSystem.h文件
#ifndef _ROADSYSTEM_H_
#define _ROADSYSTEM_H_

#include <iostream>
#include <fstream>
#include <map>
#include <list>
#include <queue>
#include <vector>

#include "Road.h"
#include "City.h"

using namespace std;

class Cheapest {

public:
Cheapest() {}

bool operator()(City* city1, City* city2) {

return city1->total_fee > city2->total_fee;
}

};

class RoadSystem {

private:
map<string, list<Road*> > outgoing_roads;
map<string, City*> cities;

void load_roads(const string& filename);
void reset(void);
string recover_route(const string& city);
pair<int, int> calc_route(string from, string to);

public:

RoadSystem(const string& filename);//带参数的构造函数,从文件中读取地图信息
~RoadSystem(void);//析够函数

void output_cheapest_route(const string& from, const string& to, ostream& out);
bool is_valid_city(const string& name);
};

#endif

RoadSystem.cpp文件
派生到我的代码片

#pragma warning (disable:4786)
#pragma warning (disable:4503)

#include "RoadSystem.h"

void RoadSystem::reset(void) {

map<string, City*>::iterator it;
for(it=cities.begin();it!=cities.end();++it) {
it->second->visited = false;
it->second->total_fee = INT_MAX;
it->second->total_distance = INT_MAX;
it->second->from_city = "";
}
}

string RoadSystem::recover_route(const string& city) {

string route;
string current = city;

while (current != "") {

route = current + route;
string prev = cities[current]->from_city;

if (prev != "") {
route = " -> " + route;
}
current = prev;
}

return route;
}

RoadSystem::RoadSystem(string const &filename) {

load_roads(filename);
}

RoadSystem::~RoadSystem(void) {

// 释放城市信息
map<string, City*>::iterator city_it = cities.begin();
for ( ; city_it != cities.end(); city_it++) {
delete city_it->second;
}

// 释放道路信息
map<string, list<Road*> >::iterator roads_it =
outgoing_roads.begin();
for ( ; roads_it != outgoing_roads.end(); roads_it++) {

list<Road*>::iterator road_it = roads_it->second.begin();
for ( ; road_it != roads_it->second.end(); road_it++) {
delete *road_it;
}
}
}

void RoadSystem::load_roads(string const &filename) {

ifstream inf(filename.c_str());
string from, to;
int fee, distance;

while ( inf.good() ) {

// 读入出发城市,目的城市,费用和路程信息
inf >> from >> to >> fee >> distance;

if ( inf.good() ) {

Road* s = new Road(to, fee, distance);

// 在cities容器中加入实体
if (cities.count(from) == 0) {
cities[from] = new City(from);
outgoing_roads[from] = list<Road*>();
}

if (cities.count(to) == 0) {
cities[to] = new City(to);
outgoing_roads[to] = list<Road*>();
}

// 为城市添加道路
outgoing_roads[from].push_back(s);

}
}

inf.close();
}

//输出结果
void RoadSystem::output_cheapest_route(const string& from,
const string& to, ostream& out) {

reset();
pair<int, int> totals = calc_route(from, to);

if (totals.first == INT_MAX) {
out <<"从"<< from << "到" << to << "之间不存在可达的路径。"<<endl;
} else {
out << "从" << from << "到" << to << "之间最便宜的路径需要花费"<< totals.first << "澳元。"<<endl;
out << "该路线全长" << totals.second << "千米。" <<endl;
cout << recover_route(to) << endl << endl;
}
}

bool RoadSystem::is_valid_city(const string& name) {

return cities.count(name) == 1;
}

//迪克斯特拉算法计算最短路径
pair<int, int> RoadSystem::calc_route(string from, string to) {

// 用优先队列来获得下一个费用最低的城市
priority_queue<City*, vector<City*>, Cheapest> candidates;
City* start_city = cities[from];

// 将起始城市添加到队列中
start_city->total_fee = 0;
start_city->total_distance = 0;
candidates.push(start_city);

// 如果优先队列不空则循环
while(!candidates.empty()) {

City* visiting_city;
visiting_city = candidates.top();
candidates.pop();

if (! visiting_city->visited) {
visiting_city->visited = true;

// 循环检查与该城市相连的各条公路
list<Road*>::iterator it;
for(it= outgoing_roads[visiting_city->name].begin();
it != outgoing_roads[visiting_city->name].end(); ++it) {

City* next_city = cities[(*it)->destination];
int next_fee = (*it)->fee + visiting_city->total_fee;

// 迪克斯特拉算法修改标记处
if((next_fee < next_city->total_fee)
&& next_city->name != from ) {
next_city->total_fee = next_fee;
next_city->total_distance =
(*it)->distance + visiting_city->total_distance;
next_city->from_city = visiting_city->name;
candidates.push(next_city);
}
}
}
}

// 返回总的费用和总的路程
if (cities[to]->visited) {
return pair<int,int>(cities[to]->total_fee, cities[to]->total_distance);
} else {
return pair<int,int>(INT_MAX, INT_MAX);
}
}

main.cpp文件
派生到我的代码片

#pragma warning (disable:4786)
#pragma warning (disable:4503)

#include <iostream>
#include <fstream>
#include <string>
#include <list>
#include <map>
#include <queue>

#include "City.h"
#include "Road.h"
#include "RoadSystem.h"

using namespace std;

int main() {

try {

RoadSystem rs("MapInformation.txt");

while (true) {

cerr << endl << endl <<"请输入起点城市和终点城市: (退出请输入'quit')"<<endl;

string from, to;
cin >> from;
if (from == "quit") break;
cin >> to;

if (rs.is_valid_city(from) && rs.is_valid_city(to)) {
rs.output_cheapest_route (from, to, cout);
}
else {
cout << "无此城市, 请确认后重试!"<<endl<<endl;
}

}

return EXIT_SUCCESS;

}
catch (exception& e) {
cerr << e.what() << endl;
}
catch (...) {
cerr << "程序出现异常, 请退出程序后重试。"<<endl;
}

return EXIT_FAILURE;
}

MapInformation.txt文件
Deloraine Queenstown 42 176
Deloraine Oatlands 25 84
Deloraine Launceston 12 50
Hobart Oatlands 18 84
Launceston Deloraine 12 50
Launceston Swansea 35 134
Oatlands Deloraine 25 84
Oatlands Hobart 18 84
Oatlands Queenstown 60 260
Oatlands Swansea 22 113
Queenstown Oatlands 60 260
Queenstown Deloraine 42 176
Swansea Launceston 35 134
Swansea Oatlands 22 113
Burnie Devonport 10 49
Devonport Burnie 10 49
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: