问题描述:
一个城市有若干公交线路,一个公交线路中的相邻两个站点需要运行的时间是已知的,假设在所有公交线路中任意两个相邻站点之间的耗时都是相同的,计算任意两个站点的最小时间。
基本要求:
(1)建立城市的若干公交线路,要求公交线路不得少于5个,站点总数不得少于10个;
(2)根据输入的两个站点计算出需要的最短时间及其路径;
提高要求:
- 公交线路存入文件中,从文件中调入数据并解决(2);
- 随机生成公交线路数据并解决(2)。
#include <iostream>
#include <ctime>
#include <cstdlib>
#include <fstream>
#include <string>
using namespace std;
const int MAX = 100; // 顶点数目的最大值
const int INF = 65535; // 表示无穷
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
class BUS{
public:
int LocateVex(string v); //求顶点下标
void Add_B(string s); //增加顶点
void Add_line(int a, int b); //增加路线
bool checking(string v); //查重
void B_show(); //显示站点
void ShortestPath_Dijkstra(); //求最短路径
void B_init(); //初始化路径
void B_print(); //显示路径
void B_random(); //随机生成路径
void Readfile(string fileName); //读取文件
void Menu(); //菜单
private:
string Vexs[MAX] = {}; // 顶点表
int Edge[MAX][MAX] = {}; // 邻接矩阵
int Visited[MAX]; //是否被访问过
int len = 0;
};
int BUS::LocateVex(string v)
{
int num = -1;
for(int i=0; i<len; i++)
{
if(Vexs[i] == v)
{
num = i;
}
}
return num;
}
void BUS::Add_B(string s)
{
Vexs[len++] = s;
}
void BUS::Add_line(int a, int b)
{
Edge[a][b] = 1;
Edge[b][a] = 1;
}
bool BUS::checking(string v)
{
for(int i=0; i<len; i++)
{
if(v == Vexs[i])
{
cout << "已有该站点,请勿重复添加。" << endl;
return false;
}
}
return true;
}
void BUS::B_show()
{
int t = 0;
if(len == 0)
{
cout<<"当前没有公交站点"<<endl;
}
cout << "当前共有" << len << "个公交站点" << endl;
if(len > 0)
{
for(int i=0; i<len; i++)
{
cout << "***" ;
}
cout << endl;
for(int i=0; i<len; i++)
{
cout << Vexs[i] << " ";
}
}
cout << endl;
t = t+len;
for(int i=0; i<t; i++)
{
cout << "***" ;
}
}
void BUS::B_init()
{
for(int i=0; i<len; i++)
{
for(int j=0; j<len; j++)
{
Edge[i][j] = 0;
}
}
len = 0;
}
void BUS::ShortestPath_Dijkstra() {
string Path[MAX] = {}; // 用于存储最短路径中经过的顶点
int Dist[MAX] = {}; // 用于存储各个最短路径的长度
bool Visited[MAX] = {false}; // 是否已找到最短距离
string first, last;
int c, d;
for (int i = 0; i < len; i++)
{
Dist[i] = INF;
Path[i] = ""; // 将路径初始化为空串
}
cout << "请输入您要查询的两个站点:" << endl;
cin >> first;
c = LocateVex(first);
Dist[c] = 0;
Path[c] = first;
cin >> last;
d = LocateVex(last);
while (true) {
int minDist = INF;
int nextNode = -1; // 用于存储下一个节点的索引
// 选择距离最短且未被访问的节点
for (int i = 0; i < len; i++) {
if (!Visited[i] && Dist[i] < minDist)
{
minDist = Dist[i];
nextNode = i;
}
}
if (nextNode == -1) {
break; // 所有可达节点都已被标记为已访问,退出循环
}
// 更新路径和距离
c = nextNode;
Visited[c] = true;
for (int i = 0; i < len; i++)
{
if (!Visited[i] && Edge[c][i] != 0)
{
if (Dist[c] + Edge[c][i] < Dist[i])
{
Dist[i] = Dist[c] + Edge[c][i];
Path[i] = Path[c] + " " + Vexs[i];
}
}
}
}
if (Dist[d] == INF)
{
cout << "无路径" << endl;
}
else {
cout << "路径:" << Path[d] << endl;
cout << "路径长度:" << Dist[d] << endl;
}
}
void BUS::B_print()
{
if(len == 0)
{
cout << "当前没有路线" ;
return;
}
cout << "当前路线如下:" << endl;
for(int i=0; i<len; i++)
{
cout << "::::::" ;
}
cout << "::::::::::" << endl;
for(int i=0; i<len; i++)
{
cout << ":: " ;
for(int j=0; j<len; j++)
{
cout << Edge[i][j] << " " ;
}
cout << " ::" << endl;
}
for(int i=0; i<len; i++)
{
cout << "::::::";
}
cout << "::::::::::" ;
}
void BUS::B_random() {
if (len < 2) {
cout << "站点过少,无法产生路线" << endl;
return;
}
bool used[len] = { false }; // 用于记录站点是否已经被选择
for (int i = 0; i < len; i++) {
used[i] = false;
}
// 清空存储路线信息的矩阵
for (int i = 0; i < len; i++)
{
for (int j = 0; j < len; j++)
{
Edge[i][j] = 0;
}
}
srand((unsigned)time(NULL)); // 初始化随机数种子
int n = 10 + rand() % (len * (len - 1) / 2 - 9); // 生成10到len*(len-1)/2之间的随机数作为路线数量
for (int i = 0; i < n; i++)
{
int a, b;
// 在0到len-1之间随机选择不重复的起点和终点
do {
a = rand() % len;
b = rand() % len;
} while (a == b);
Add_line(a, b);
}
cout << "生成成功" << endl;
}
void Menu()
{
cout << ":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::" << endl;
cout << ":: ::" << endl;
cout << ":: ::" << endl;
cout << ":: ***************公交车站点的最短路径************* ::" << endl;
cout << ":: ::" << endl;
cout << ":: ::" << endl;
cout << ":: ******** 1. 添加站点 ********** ::" << endl;
cout << ":: ******** 2. 添加路线 ********** ::" << endl;
cout << ":: ******** 3. 显示站点 ********** ::" << endl;
cout << ":: ******** 4. 计算最短路径 ********** ::" << endl;
cout << ":: ******** 5. 显示路线 ********** ::" << endl;
cout << ":: ******** 6. 随机生成路径 ********** ::" << endl;
cout << ":: ******** 7. 读取文件 ********** ::" << endl;
cout << ":: ******** 8. 退出 ********** ::" << endl;
cout << ":: ::" << endl;
cout << ":: ::" << endl;
cout << ":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::" << endl;
}
void BUS::Readfile(string fileName) {
ifstream infile(fileName);
if (!infile)
{
cout << "Failed to open file: " << fileName << std::endl;
return;
}
string line;
if (fileName == "Vexs.txt")
{
while (getline(infile >> std::ws,line))
{
Vexs[len++] =line;
}
}
else if (fileName == "Edge.txt")
{
for (int i = 0; i < len; i++)
{
for (int j = 0; j < len; j++)
{
if (infile >> Edge[i][j]) {
// 成功读取一个元素
} else {
// 读取失败,处理错误
cout << "Error reading Edge.txt at index (" << i << ", " << j << ")" << std::endl;
infile.close();
return;
}
}
}
}
infile.close();
}
int main(int argc, char** argv) {
BUS bus;
int len = 0;
string Vexs[MAX] = {};
int choice;
do {
Menu();
cout << "请输入您的选择(1-7):"<<endl;
cin >> choice;
switch(choice)
{
case 1:
{
cout << "需要保留原有数据吗?" << endl;
cout << "1:保留 2:不保留" << endl;
int c;
int n;
cin >> c;
if(c == 2)
{
bus.B_init();
}
cout << "请问您需要添加几个公交车站点?" << endl;
cin >> n ;
cout<<"请输入站点名称:"<<endl;
for(int i=0; i<n; i++)
{
string s;
cin >> s;
if(bus.checking(s))
{
bus.Add_B(s);
cout<<"加入成功"<<endl;
len++;
}
}
cout << "目前已有" << len << "个公交站点" << endl;
cout << "按任意键返回" ;
system("pause");
system("cls");
break;
}
case 2:
{
bus.B_show();
cout << endl;
int m;
cout << "您要添加几条路线?" << endl;
cin >> m;
for(int i=0; i<m; i++)
{
cout << "请输入您要添加路线的两个站点:" << endl;
string v1,v2;
int a, b;
cin >> v1;
a = bus.LocateVex(v1);
cin >> v2;
b = bus.LocateVex(v2);
bus.Add_line(a, b);
cout << "已添加成功!" << endl;
}
system("pause");
system("cls");
break;
}
case 3:
{
cout << "显示站点" << endl;
bus.B_show();
system("pause");
system("cls");
break;
}
case 4:
{
bus.B_show();
bus.ShortestPath_Dijkstra();
system("pause");
system("cls");
break;
}
case 5:
{
bus.B_show();
bus.B_print();
system("pause");
system("cls");
break;
}
case 6:
{
bus.B_random();
bus.B_print();
system("pause");
system("cls");
break;
}
case 7:
{
bus.Readfile("Vexs.txt");
bus.Readfile("Edge.txt");
cout << "文件读取文件成功!!" << endl;
bus.B_show();
bus.B_print();
system("pause");
system("cls");
break;
}
case 8:
{
exit(0);
getchar();
break;
}
}
} while(choice != 0);
return 0;
}
求最短路径运行结果图:
读取的文件内容:
读取文件的结果图示:
代码有点小问题,已更新至最新版!!!