目录
一、题目与设计内容
交通咨询系统设计
设计内容:
设计一个交通咨询系统,能让旅客咨询从任一个城市定点到另一个城市定点之间的最短路径或最低花费或最少时间等问题。对于不同的咨询要求、可输入城市间的路程或所需时间或所需花费。
二、需求分析
1.设计要求:
1. 建立交通网络网的存储结构。
2. 总体设计要画流程图。
3. 提供程序测试方案。
4. 界面友好。
2.规定:
1.输入的形式和输入值的范围: 在程序中输入城市名称时,需输入20个字符以内的字符串;
2.输出的形式:最短路径;
3.程序所能达到的功能:熟练掌握迪杰斯特拉算法和费洛伊德算法,能够利用它们解决最短路径问题;能够解决工程项目实施过程中的关键路径问题;
4.测试数据:通过输入不同的省会,得到最短的距离。
三、概要设计
1.抽象数据类型的定义:
class Gragh
{
private:
const char* a[34];
int edge[34][34];
int n, e, path_num;
bool Mark[34];
int Path[50][11];
int Path_date[50];
int result[34];
public:
Gragh();
void creat_Gragh();
int find(string str);
void BFT(Gragh g);
void Dijkstra(string str1, string str2, string str3 = "无");
void Floyd(string str1, string str2, string str3 = "无");
void All_Load(string str1, string str2);
void Find_All_Load(int pos1, int pos2);
void A_star(string str1, string str2, int k);
};
struct edge1
int num;
int cost, last_cost;
string str;
bool operator <(const edge1& s)const
{
return cost > s.cost;
};
2.数据的逻辑结构:
根据设计任务的描述,其城市之间的交通问题是典型的图结构,可看作为有向图,图的顶点是城市,边是城市之间所耗费的里程。
3.主程序流程:
主程序可以有系统界面、菜单;也可用命令提示方式;选择功能模块执行,要求在程序运行过程中可以反复操作。说明本程序中用到的所有抽象数据类型的定义、数据的逻辑结构、主程序的流程以及各程序模块之间的层次(调用)关系。
四、调用关系图
五、程序代码
graph.h:
#include<iostream>
#include<fstream>
#include<sstream>
#include<string>
#include<queue>
#include<stack>
using namespace std;
const int MAX = 10000;
void quickSort(int left, int right, int a[], string s[], int size);
class Gragh
{
private:
const char* a[34];
int edge[34][34];
int n, e, path_num;
bool Mark[34];
int Path[50][11];
int Path_date[50];
int result[34];
public:
Gragh();
void creat_Gragh();
int find(string str);
void BFT(Gragh g);
void Dijkstra(string str1, string str2, string str3 = "无");
void Floyd(string str1, string str2, string str3 = "无");
void All_Load(string str1, string str2);
void Find_All_Load(int pos1, int pos2);
void A_star(string str1, string str2, int k);
};
struct edge1
int num;
int cost, last_cost;
string str;
bool operator <(const edge1& s)const
{
return cost > s.cost;
}
};
Gragh::Gragh()
{
for (int i = 0; i < 50; i++)
{
Path_date[i] = 0;
for (int j = 0; j < 11; j++)
Path[i][j] = -1;
}
for (int i = 0; i < 34; i++)
{
Mark[i] = false;
result[i] = 0;
for (int j = 0; j < 34; j++)
{
if (i == j) edge[i][j] = 0;
else edge[i][j] = MAX;
}
}
n = 0;
path_num = 0;
}
void Gragh::creat_Gragh()
{
int temp[600] = { 0 };
string str;
{
ifstream fin_2("2.csv");
for (int tem = 0; fin_2.eof() == false; tem++)
{
getline(fin_2, str, ',');
if (str == "0")
{
getline(fin_2, str, '\n');
getline(fin_2, str, ',');
cin.sync();
}
istringstream is(str);
is >> temp[tem];
}
}
ifstream fin_3("3.csv");
for (int i = 0; i < 34; i++)
{
getline(fin_3, str, ',');
string* str_1 = new string(str);
a[i] = str_1->c_str();
}
ifstream fin_1("1.csv");
for (int i = 0; i < 34; i++)
{
for (int j = 0; j < 34; j++)
{
if (j == 33)
{
getline(fin_1, str, '\n');
if (str != "1" || j < i) continue;
edge[j][i] = edge[i][j] = temp[(j * j - j) / 2 + i];
}
getline(fin_1, str, ',');
if (str != "1" || j < i) continue;
edge[j][i] = edge[i][j] = temp[(j * j - j) / 2 + i];
}
}
}
int Gragh::find(string str)
{
if (str == "无") return 0;
for (int i = 0; i < 34; i++)
{
if (a[i] == str) return i;
}
return -1;
}
void Gragh::BFT(Gragh g)
{
int have[34] = { 0 };
have[22] = 1;
int num = 0;
queue<int> q1;
for (int i = 0; i < 34; i++)
{
if (g.edge[22][i] < MAX && g.edge[22][i]>0)
{
q1.push(i);
have[i] = 1;
}
}
q1.push(-1);
while (!q1.empty())
{
int i = q1.front();
q1.pop();
if (i == -1)
{
cout << endl;
cout << "上面城市需要" << num << "次中转即可到达" << endl;
cout << endl;
if (q1.empty()) return;
q1.push(-1);
num++;
continue;
}
cout << a[i] << " ";
for (int j = 0; j < 34; j++)
{
if (g.edge[i][j] < MAX && g.edge[i][j]>0 && have[j] == 0)
{
have[j] = 1;
q1.push(j);
}
}
}
}
void Gragh::Dijkstra(string str1, string str2, string str3)
{
int i, j, k, w, min, pos1 = find(str1), pos2 = find(str2), pos3 = find(str3), temp = pos1;
if (pos1 == -1 || pos2 == -1 || pos3 == -1)
{
cout << "本路线图不存在您所给出的城市,请重试" << '\n';
return;
}
int dist[34], path[34];
bool s[34];
for (i = 0; i < 34; i++)
{
dist[i] = edge[pos1][i];
s[i] = false;
if (i != pos1 && dist[i] < MAX && dist[i]>0) path[i] = pos1;
else path[i] = -1;
}
s[pos1] = true;
dist[pos1] = 0;
for (i = 0; i < 33; i++)
{
if (i == pos3) continue;
min = MAX;
int u = pos1;
for (j = 0; j < 34; j++)
{
if (j == pos3) continue;
if (!s[j] && dist[j] < min)
{
u = j;
min = dist[j];
}
}
s[u] = true;
for (k = 0; k < 34; k++)
{
if (k == pos3) continue;
w = edge[u][k];
if (!s[k] && w < MAX && dist[u] + w < dist[k])
{
dist[k] = dist[u] + w;
path[k] = u;
}
}
}
k = path[pos2];
if (k == -1)
{
cout << "此路径不存在" << '\n';
return;
}
stack<int> sta;
cout << str1;
while (k != pos1)
{
sta.push(k);
k = path[k];
}
while (!sta.empty())
{
cout << "->" << a[sta.top()];
sta.pop();
}
cout << "->" << str2 << " " << "距离为" << dist[pos2] << endl;
}
void Gragh::Floyd(string str1, string str2, string str3)
{
int i, j, k, pos1 = find(str1), pos2 = find(str2), pos3 = find(str3), temp = pos1;
if (pos1 == -1 || pos2 == -1 || pos3 == -1)
{
cout << "本路线图不存在您所给出的城市,请重试" << '\n';
return;
}
int min[34][34], path[34][34];
for (i = 0; i < 34; i++)
for (j = 0; j < 34; j++)
{
min[i][j] = edge[i][j];
path[i][j] = j;
}
pos1 = temp;
for (k = 0; k < 34; k++)
{
if (k == pos3) continue;
for (i = 0; i < 34; i++)
{
if (i == pos3) continue;
for (j = 0; j < 34; j++)
{
if (j == pos3) continue;
if (min[i][j] > min[i][k] + min[k][j])
{
min[i][j] = min[i][k] + min[k][j];
path[i][j] = path[i][k];
}
}
}
}
k = path[pos1][pos2];
if (k == pos2)
{
cout << "此路径不存在" << '\n';
return;
}
cout << str1;
while (k != pos2)
{
cout << "->" << a[k];
k = path[k][pos2];
}
cout << "->" << str2 << " " << "距离为" << min[pos1][pos2] << endl;
}
void Gragh::All_Load(string str1, string str2)
{
string s[100];
int date[100];
int pos1 = find(str1);
int pos2 = find(str2);
if (pos1 == -1 || pos2 == -1)
{
cout << "未查询到城市名字,请重新再试" << endl;
return;
}
Find_All_Load(pos1, pos2);
for (int i = 0; i < path_num; i++)
{
for (int j = 0; j < 10; j++)
{
s[i] += a[Path[i][j]];
if (Path[i][j + 1] == -1) break;
s[i] += "->";
}
}
quickSort(0, path_num, Path_date, s, path_num + 1);
ofstream out("path_date.txt");
if (!out) { cout << "不能打开文件!" << endl; return; }
for (int i = 0; i < path_num; i++)
{
out << s[i] << " 路径长度为" << Path_date[i] << endl;
}
cout << "已保存在文件中" << endl;
}
void Gragh::Find_All_Load(int pos1, int pos2)
{
if (n > 5) return;
result[n] = pos1;
Mark[pos1] = true;
n++;
while (n != 0)
{
int temp = result[n - 1];
if (temp == pos2)
{
for (int i = 0; i < n; i++)
{
Path[path_num][i] = result[i];
if (i != 0) Path_date[path_num] += edge[result[i - 1]][result[i]];
}
n--;
path_num++;
result[n] = 0;
Mark[pos2] = false;
break;
}
for (int j = 0; j < 34; j++)
{
if (edge[temp][j] > 0 && edge[temp][j] < MAX)
{
if (Mark[j] == false)
{
Find_All_Load(j, pos2);
}
}
}
n--;
result[n] = 0;
Mark[pos1] = false;
break;
}
}
void quickSort(int left, int right, int a[], string s[], int size)
{
if (left >= right)
return;
if (left < 0 || right >= size)
{
cout << "error args! aay bound." << endl;
return;
}
int i, j, base, temp;
i = left, j = right;
base = a[left];
while (i < j)
{
while (a[j] <= base && i < j)
j--;
while (a[i] >= base && i < j)
i++;
if (i < j)
{
swap(s[i], s[j]);
temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
//基准数归位
a[left] = a[i];
a[i] = base;
swap(s[i], s[left]);
quickSort(left, i - 1, a, s, size);
quickSort(i + 1, right, a, s, size);
}
void Gragh::A_star(string str1, string str2, int k_num)
{
int i, j, k, w, min, pos1 = find(str2), pos2 = find(str1), temp = pos1;
if (pos1 == -1 || pos2 == -1)
{
cout << "本路线图不存在您所给出的城市,请重试" << '\n';
return;
}
int dist[34], path[34];
bool s[34];
for (i = 0; i < 34; i++)
{
dist[i] = edge[pos1][i];
s[i] = false;
if (i != pos1 && dist[i] < MAX && dist[i]>0) path[i] = pos1;
else path[i] = -1;
}
s[pos1] = true;
dist[pos1] = 0;
for (i = 0; i < 33; i++)
{
min = MAX;
int u = pos1;
for (j = 0; j < 34; j++)
{
if (!s[j] && dist[j] < min)
{
u = j;
min = dist[j];
}
}
s[u] = true;
for (k = 0; k < 34; k++)
{
w = edge[u][k];
if (!s[k] && w < MAX && dist[u] + w < dist[k])
{
dist[k] = dist[u] + w;
path[k] = u;
}
}
}
priority_queue <edge1> Q;
edge1 tem;
tem.cost = dist[pos2];
tem.num = pos2;
tem.last_cost = 0;
tem.str = str1;
Q.push(tem);
while (!Q.empty())
{
tem = Q.top();
Q.pop();
if (tem.num == pos1)
if (--k_num == 0)
{
cout << tem.str << " 路径长度为" << tem.cost << endl;
return;
}
for (int i = 0; i < 34; i++)
{
if (edge[tem.num][i] <= 0 || edge[tem.num][i] >= MAX) continue;
edge1 tp;
tp.str = tem.str + "->" + a[i];
tp.num = i;
tp.cost = tem.last_cost + edge[tem.num][tp.num] + dist[tp.num];
tp.last_cost = tem.last_cost + edge[tem.num][i];
Q.push(tp);
}
}
return;
}
void menu()
{
cout << " ------------------------------------------------------------------" << endl;
cout << " | | " << endl;
cout << " | 如需验证武汉中心地位请按 1 | " << endl;
cout << " | 如需使用Dijkstra查询两城市之间的最短距离请按 2 | " << endl;
cout << " | 如需使用Floyd查询两城市之间的最短距离请按 3 | " << endl;
cout << " | 如需输出所有路径请按 4 | " << endl;
cout << " | 如需求出两城市间第k短距离请按 5 | " << endl;
cout << " | 如需退出系统请按 0 |" << endl;
cout << " | | " << endl;
cout << " -----------------------------------------------------------------" << endl;
}
graph.cpp:
#include <iostream>
#include <string>
#include "graph.h"
using namespace std;
int main()
{
int k;
int k_num;
Gragh g;
g.creat_Gragh();
string str1, str2, str3;
while (1)
{
menu();
cout << "请问您要执行哪一个功能呢,请输入相应数字" << endl;
cin >> k;
switch (k)
{
case 1:
g.BFT(g);
break;
case 2:
cout << "请输入您想要查询的两城市名字" << endl;
cin >> str1 >> str2;
cout << "您是否有想过要绕过的城市(如有则输入城市名称,如无则输入“0”)" << endl;
cin >> str3;
if (str3 == "0") g.Dijkstra(str1, str2);
else g.Dijkstra(str1, str2, str3);
break;
case 3:
cout << "请输入您想要查询的两城市名字" << endl;
cin >> str1 >> str2;
cout << "您是否有想过要绕过的城市(如有则输入城市名称,如无则输入“0”)" << endl;
cin >> str3;
if (str3 == "0") g.Floyd(str1, str2);
else g.Floyd(str1, str2, str3);
break;
case 4:
cout << "请输入您想要查询的两城市名字" << endl;
cin >> str1 >> str2;
g.All_Load(str1, str2);
break;
case 5:
cout << "请输入您想要查询的两城市名字" << endl;
cin >> str1 >> str2;
cout << "请输入k的值" << endl;
cin >> k_num;
g.A_star(str1, str2, k_num);
break;
case 0:
exit(0);
default:
break;
}
}
}
六、测试结果
七、尾言
在本文中,我们探讨了设计一个交通咨询系统的全过程,该系统允许旅客查询从一个城市到另一个城市的最短路径、最低花费或最少时间等关键信息。我们首先进行了需求分析,明确了系统的设计要求和规定。接下来,我们进行了概要设计,包括抽象数据类型的定义、数据的逻辑结构以及主程序流程的设计。这些步骤为编写具体的程序代码打下了坚实的基础。
在实现阶段,我们采用了C++语言和合适的数据结构来编码交通咨询系统,确保它能够高效地处理城市间路径、时间及费用信息的查询。我们通过调用关系图来展示系统中各个组件如何相互作用。完成编写后,我们进行了程序的测试,验证系统能否正常运行并生成正确的咨询结果。
测试结果表明,该系统能够准确地回答用户关于城市间最短路径、最低花费和最少时间等的查询。它在功能上表现稳定,用户界面友好,易于旅客使用,能够快速得到他们所需的重要旅行信息。
综上所述,我们的交通咨询系统设计是成功的。它不仅满足了旅客查询交通信息的需求,还展示了如何将理论知识应用于解决实际问题的过程。随着交通数据的不断更新和变化,系统应能容易地进行维护和升级,以适应未来的发展和扩大服务范围。我们希望这个系统能够为旅客提供便利,并提高他们的旅行体验。