东华大学数据结构课程设计2024

老师要求做一个地铁线路查询,有以下功能

地铁系统功能

  • 构造图
  1. 【顶点信息输入】(基本功能)线路信息输入-》(进阶功能)换乘时间权重输入,不同站点之间时间的输入,保存到文件中(用流输入)【需要上海地铁路线图】
  2. 【边信息输入】(基本功能)换乘信息输入(明确哪些站点是相连的)

  • 查询图
  1. 【按线路这一性质遍历顶点并输出每个顶点的相邻顶点】(基本功能)线路查询(输出一条地铁线所有站点及换乘信息)
  2. 【最短路径算法/弗洛伊德或者迪杰斯特拉】(基本功能)每两个站距离为1,换乘时间为0,输出最短路径(要考虑可能需要换乘)-》(进阶功能)考虑换乘时间,站点间距离按输入的时间计算,输出时间最短的路径和换乘次数最少的路径
  3. 基本功能)菜单:输入,修改和查询路线-》(进阶功能)用户界面增强(要做的话可以用QT)

  • 修改图

1、【增加/输出顶点及关联边】(基本功能)增加/减少站点数

2、【增加/删除边】(基本功能)增加/减少换乘关系

3、【删除顶点所有关联边】(基本功能)封闭线路区间(由于之后要恢复,所以不能直接删,只能标记一下

4、【重新添加顶点所有关联边】(基本功能)恢复线路区间

目前除了修改图实现的不是很完美(还有QT完全不会搞),别的全部实现(可能还有些BUG)

废话不多说直接上代码


#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <map>
#include <unordered_map>
#include <stack>
#include <queue>
#include <fstream>
#include <filesystem>

using namespace std;
#define INF 9999999
#define SIZE 30
#define MAX 100
struct metro
{
	int size;
	bool have[SIZE];
};
//vector<pair<int,int> > V;//地铁站所在地铁线路(换乘站可能在2条地铁线路上)
struct exc
{
	string stationn;
	int exname;
};
map<string, int> M1;
map<int, string> M2;
vector<vector<int> > V;
struct Line1 {
	int Lnum;//线路编号
	int stationNum=0; //站台数
	int exnum=0;
	vector<string> v;//站名
	vector<int> w;//weight
	vector<exc> ex;
};
vector<Line1> Line(SIZE);
struct Graph_b {
	vector<vector<int> > adj;//邻接表存图
	int vexnum;
	Graph_b(int n) :vexnum(n) 
	{
		vexnum = n;
		vector<int> v;
		adj.resize(n, v);
	}
};
struct vertex 
{
	bool known;//记录顶点是否访问过
	int dist; //在Dijkstra中记录路径的长度
	int path;//记录上一个顶点
};

struct Graph_a
{
	int vexnum;
	int arcnum;
	vector<vertex> v;
	vector<vector<pair<int, int> > > adj;//int 编号 int 权重;
	Graph_a(int n) :vexnum(n) 
	{
		vector<pair<int, int> > V;
		vertex ver;
		v.resize(n + 1, ver);
		adj.resize(n + 1, V);
		for (int i = 0;i < n;i++) 
		{
			v[i] = { false,INT_MAX,-1 };//对顶点的信息进行初始化
		}
	}
};

void read(int i, string fileName, int& cnt) {//i 地铁线路Line的下标  fileName 存放地铁线路信息的txt文件的文件名  cnt 顶点编号
	FILE* fp;
	int j, p;
	fp = fopen(fileName.c_str(), "r");
	if (fp == NULL) {
		cout << "Can not open the file!\n";
		exit(0);
	}
	p = fscanf(fp, "%d %d", &(Line[i].Lnum), &(Line[i].stationNum));
	p++;
	for (j = 0;j < Line[i].stationNum;j++) {
		char Station[50];
		p = fscanf(fp, "%s", Station);
		string station = Station;
		Line[i].v.push_back(station);
		p++;
		//给地铁站编号
		map<string, int>::iterator iter = M1.find(station);
		if (iter == M1.end()) {
			M1.insert(make_pair(station, cnt));
			M2.insert(make_pair(cnt, station));
			cnt++;
			vector<int> vec;
			vec.push_back(Line[i].Lnum);
			V.push_back(vec);
		}
		else {
			V[M1[station]].push_back(Line[i].Lnum);
			//如果地铁站已经记录过,说明该地铁站是换乘站
		}
	}
	//地铁线路相邻2站所需时间
	for (j = 0;j < Line[i].stationNum - 1;j++) {
		int weight;
		p = fscanf(fp, "%d", &weight);
		Line[i].w.push_back(weight);
		p++;
	}
	
	fclose(fp);
}


//建无向带权图
Graph_a mkGraph_a()
{
	Graph_a g(V.size());
	for (int i = 0;i < SIZE;i++) {
		if(Line[i].stationNum != 0)
		for (int j = 0;j < Line[i].v.size() - 1;j++)
		{
				int weight = Line[i].w[j];
				int c = M1[Line[i].v[j]];
				int d = M1[Line[i].v[j + 1]];
				g.adj[c].push_back(make_pair(d, weight));
				g.adj[d].push_back(make_pair(c, weight));
			
		}
	}
	return g;
}
int flag2 = 1;
void print_min_d(int i, Graph_a g) {
	int j;
	int fl=0;
	if ( g.v[i].dist==0) cout << M2[i];
	else {
		if (g.v[i].path >= 0)
		{
			fl = 1;
			print_min_d(g.v[i].path, g);
			int temp = g.v[i].path;

			if (V[temp].size() > 1 && V[g.v[temp].path][0] != V[temp][0]) {
				int a = V[temp][0];
				V[temp][0] = V[temp][1];
				V[temp][1] = a;
			}
			if (V[temp].size() > 1) {
				int mark = -1;
				for (int m = 0;m < V[i].size();m++) {
					for (int n = 0;n < V[g.v[temp].path].size();n++) {
						if (V[i][m] == V[g.v[temp].path][n]) {
							mark = 1;
							break;
						}
					}
				}
				if (mark == -1) {
					int b;
					cout << "(换乘 ";
					for (int m = 0;m < V[i].size();m++) {
						for (int n = 0;n < V[temp].size();n++) {
							if (V[i][m] == V[temp][n]) {
								b = V[i][m];
								cout << V[i][m];
							}
						}
					}
					cout << " 号线 ";
					for (j = 0;j < SIZE;j++) {
						if (Line[j].Lnum == b) break;
					}
					for (int m = 0;m < Line[j].v.size();m++) {
						if (Line[j].v[m] == M2[i]) {
							if (m + 1 < Line[j].v.size() && Line[j].v[m + 1] == M2[temp])
								cout << "往 " << Line[j].v[0] << " 方向列车)";
							else if (m - 1 >= 0 && Line[j].v[m - 1] == M2[temp]) {
								int a = Line[j].v.size() - 1;
								cout << "往 " << Line[j].v[a] << " 方向列车)";
							}
						}

					}
				}
			}
			cout << "->" << M2[i];
		}
	}
	if (fl == 0)
	{
		cout << "未查询到路径\n";
		cout << "输入任意键+回车返回\n";
		int a;
		if(cin>>a)
		system("cls");
	}
}

void MinDist(string v1, string v2, Graph_a g) {
	int a = M1[v1];
	int b = M1[v2];
	g.v[a] = { true,0,a };

	int i, j, k;
	for (i = 0;i < g.adj[a].size();i++) {
		g.v[g.adj[a][i].first].dist = g.adj[a][i].second;
	}
	for (i = 1;i < g.vexnum;i++) {
		int min = INT_MAX;
		for (j = 0;j < g.vexnum;j++) {
			if (!g.v[j].known && g.v[j].dist < min) {
				k = j;
				min = g.v[j].dist;
			}
		}
		g.v[k].known = true;
		if (g.v[k].path == -1) g.v[k].path = a;
		for (j = 0;j < g.adj[k].size();j++) {
			if (!g.v[g.adj[k][j].first].known && (min + g.adj[k][j].second < g.v[g.adj[k][j].first].dist)) {
				g.v[g.adj[k][j].first].dist = min + g.adj[k][j].second;
				g.v[g.adj[k][j].first].path = k;
			}
		}
	}
	cout << endl;
	cout << "最短距离的乘车方案有:" << endl;
	print_min_d(M1[v2], g);
	cout << endl;
	cout << "==================================================================================" << endl << endl;
}
Graph_b mkGraph_b_c() 
{ //最小换乘图
	Graph_b g(V.size());
	for (int i = 0;i < SIZE;i++) {
		for (int j = 0;j < Line[i].v.size();j++) {
			int temp1 = M1[Line[i].v[j]];
			for (int k = j + 1;k < Line[i].v.size();k++) {
				int temp2 = M1[Line[i].v[k]];
				g.adj[temp1].push_back(temp2);
				g.adj[temp2].push_back(temp1);
			}
		}
	}
	return g;
}
Graph_b mkGraph_b_s() {//最小站数图
	Graph_b g(V.size());
	for (int i = 0;i < SIZE;i++) {
		if(Line[i].stationNum != 0)
		for (int j = 0;j < Line[i].v.size() - 1;j++) {
			int temp1 = M1[Line[i].v[j]];
			int temp2 = M1[Line[i].v[j + 1]];
			g.adj[temp1].push_back(temp2);
			g.adj[temp2].push_back(temp1);
		}
	}
	return g;
}

void print_min_s(vector<int>from, int dest, int start) {
	cout << endl;
	cout << "最少站台数的乘车方案有:" << endl;
	int temp = dest;
	bool flag = 0;
	while (from[temp] != -1) {
		cout << M2[temp];
		//		if(V[temp].first==V[temp].second) cout<<"[line"<<V[temp].first<<"]"<<"->";
		//		else cout<<"[line"<<V[temp].first<<"&"<<V[temp].second<<"]"<<"->";
		cout << "->";
		temp = from[temp];
		flag = 1;
	}
	cout << M2[start];
	//	if(V[start].first==V[start].second) cout<<"[line "<<V[start].first<<"]"<<endl;
	//	else cout<<"[line "<<V[start].first<<"&"<<V[start].second<<"]"<<endl;
	cout << endl << endl;
	cout << "==================================================================================" << endl << endl;
}

void print_min_c(vector<int>from, int dest, int start) {
	cout << endl;
	cout << "最少转乘数的乘车方案有:" << endl;
	int temp = dest;
	int n = 0;
	while (from[temp] != -1) {
		n++;
		for (int a = 0;a < V[temp].size();a++) {
			for (int b = 0;b < V[from[temp]].size();b++) {
				if (V[temp][a] == V[from[temp]][b]) {
					cout << M2[temp] << "-[沿" << V[temp][a] << "号线一直到]->";
				}
			}
		}
		//		if(V[temp].first==V[from[temp]].first||V[temp].first==V[from[temp]].second)
		//			cout<<M2[temp]<<"-[沿"<<V[temp].first<<"号线一直到]->";
		//		else
		//			cout<<M2[temp]<<"-[沿"<<V[temp].second<<"号线一直到]->";
		//		if(V[temp][0]==V[from[temp]][0]||V[temp][0]==V[from[temp]][1]||V[temp][0]==V[from[temp]][2])
		temp = from[temp];
	}
	cout << M2[start] << endl;
	cout << "共换乘" << n - 1 << "次" << endl;
	cout << endl;
	cout << "==================================================================================" << endl << endl;
}

void find_min(Graph_b g, int start, int dest, bool ifChange) {
	vector<int> dist;
	dist.clear();
	queue<int> q;
	vector<int> from(g.vexnum, -1);
	bool ifFind = false;
	for (int i = 0;i < g.vexnum;i++) 
	{
		dist.push_back(INF);
	}
	dist[start] = 0;
	q.push(start);
	while (!q.empty()) 
	{
		int v = q.front();
		q.pop();
		for (int i = 0;i < g.adj[v].size();i++) 
		{
			if (dist[g.adj[v][i]] == INF) {
				dist[g.adj[v][i]] = dist[v] + 1;
				from[g.adj[v][i]] = v;
				q.push(g.adj[v][i]);
				if (g.adj[v][i] == dest) 
				{
					ifFind = true;
					if (ifChange) print_min_c(from, dest, start);
					else print_min_s(from, dest, start);
				}
			}
			if (ifFind && i == g.adj[v].size() - 1)break;
		}
	}
	if (!ifFind)
	{
		cout << "没有找到乘车方案" << endl;
		cout << "输入任意键+回车返回\n";
		string a;
		if (cin >> a)
		{
			system("cls");
		}
	}
}

bool judge(string& name1, string& name2) {
	cout << endl;
	cout << "请输入出发地:";
	cin >> name1;
	if (M1.find(name1) == M1.end()) {
		cout << "查无此站,请重新操作" << endl;
		return false;
	}
	cout << "请输入目的地:";
	cin >> name2;
	if (M1.find(name2) == M1.end()) {
		cout << "查无此站,请重新操作" << endl;
		return false;
	}
	return true;
}

void MinChange_(Graph_b g) {
	string name1, name2;
	if (!judge(name1, name2)) return;
	int start = M1[name1];
	int dest = M1[name2];
	find_min(g, dest, start, true);
}

void MinDist_(Graph_a g) {
	string name1, name2;
	if (!judge(name1, name2)) return;
	int start = M1[name1];
	int dest = M1[name2];
	MinDist(name1, name2, g);
}

void MinStation_(Graph_b g) {
	string name1, name2;
	if (!judge(name1, name2)) return;
	int start = M1[name1];
	int dest = M1[name2];
	find_min(g, dest, start, false);
}
//输出全部地铁线路信息
void print_whole() {
	cout << endl;
	for (int i = 0;i < SIZE;i++) {
		if (!Line[i].v.empty()) {
			cout << endl << Line[i].Lnum << "号线:";
			cout << endl;
			for (int j = 0;j < Line[i].v.size();j++) {
				cout << Line[i].v[j] << " ";
			}
			cout << endl;
		}
	}
	cout << endl;
}
void print(int i)
{
	if (!Line[i].v.empty()) {
		cout << endl << Line[i].Lnum << "号线:";
		cout << endl;
		for (int j = 0;j < Line[i].v.size();j++) {
			cout << Line[i].v[j] << " ";
		}
		cout << endl;
		cout << "请输入任意键 + 回车返回\n";
		string a;
		if (cin >> a)
		{
			system("cls");
		}
	}
	else {
		cout << "该线未录入,请输入任意键+回车返回\n";
		string a;
		if(cin>>a)
		{
			system("cls");
		}
	}
}
void creat()
{
	cout << "请输入地铁线路编号\n";
	int num;
	cin >> num;
	cout << endl;
	string filename = "line" + to_string(num) + ".txt";
	ofstream Linea;
	Linea.open(filename);
	int n;
	cout << "请输入站点数:\n";
	cin >> n;
	cout << endl;
	cout << "请输入站点名,"<<n<<"个站点:\n";
	vector<string> sta;
	string STA = "";
	for (int i = 0;i < n;i++)
	{
		cin >> STA;
		sta.push_back(STA);
	}
	cin.ignore(std::numeric_limits< streamsize >::max(), '\n');//清空键盘缓冲区
	vector<int> wei;
	cout << "请输入站间距,"<<n-1<<"个数据";
	int w;
	for (int i = 0;i < n-1;i++)
	{
		cin >> w;
		wei.push_back(w);
	}
	cin.ignore(std::numeric_limits< streamsize >::max(),'\n');//清空键盘缓冲区
	Linea << num;
	Linea << ' ';
	Linea << n << '\n';
	for (int i = 0;i < n;i++)
	{
		Linea << sta[i] << '\n';
	}
	for (int i = 0;i < n-1;i++)
	{
		Linea << wei[i] << '\n';
	}
	Linea.close();
}
void Delete()
{
	cout << "请输入需要删除的地铁线路编号\n";
	int num;
	cin >> num;
	cout << endl;
	string filename = "line" + to_string(num) + ".txt";
	std::ofstream outFile(filename, std::ios::out | std::ios::trunc);
	outFile.close();
}
void Modfi()
{
	cout << "请输入需要修改的地铁线路编号\n";
	int num;
	cin >> num;
	cout << endl;
	string filename = "line" + to_string(num) + ".txt";
	ofstream Linea;
	Linea.open(filename);
	int n;
	cout << "请输入站点数:\n";
	cin >> n;
	cout << endl;
	cout << "请输入站点名," << n << "个站点:\n";
	vector<string> sta;
	string STA = "";
	for (int i = 0;i < n;i++)
	{
		cin >> STA;
		sta.push_back(STA);
	}
	cin.ignore(std::numeric_limits< streamsize >::max(), '\n');//清空键盘缓冲区
	vector<int> wei;
	cout << "请输入站间距," << n - 1 << "个数据";
	int w;
	for (int i = 0;i < n - 1;i++)
	{
		cin >> w;
		wei.push_back(w);
	}
	cin.ignore(std::numeric_limits< streamsize >::max(), '\n');//清空键盘缓冲区
	Linea << num;
	Linea << ' ';
	Linea << n << '\n';
	for (int i = 0;i < n;i++)
	{
		Linea << sta[i] << '\n';
	}
	for (int i = 0;i < n - 1;i++)
	{
		Linea << wei[i] << '\n';
	}
	Linea.close();
}
void mod()
{
	cout << "请选择功能\n1:新增线路\n2:删除线路\n3:修改线路\n";
	char order;
	cin >> order;
	switch (order)
	{
	case '1':
	{
		creat();
		break;
	}
	case '2':
	{
		Delete();
		break;
	}
	case '3':
	{
		Modfi();
		break;
	}
	default:
	{
		cout << "请输入正确的参数\n";
		cout << "按任意键+回车返回\n";
		cin.get();
		char cho;
		cin.get(cho);

	}
	system("cls");

	}
}
bool isFileEmpty(const std::string& filename) 
{
	
	ifstream ifs;
	ifs.open(filename, ios::in);
	if (ifs.eof())
	{
		ifs.close();
		return 1;
	}
	ifs.close();
	return 0;
}
int main()
{
	while (1)
	{
		system("color f4");//color f4
		//读文件函数
		int n = 0;
		for (int i = 0;i < SIZE;i++) 
		{
			string filename = "line" + to_string(i) + ".txt";
			if (!isFileEmpty(filename)) 
			{
				read(i, filename, n);
			}
		}
		Graph_a ga = mkGraph_a();
		Graph_b gc = mkGraph_b_c();
		Graph_b gs = mkGraph_b_s();

		cout << "*************欢迎来到上海地铁*************" << endl
			<< "|   1 ---------查看线路及站点------------|" << endl
			<< "|   2 -------按最短距离查询路线----------|" << endl
			<< "|   3 -------按最小换乘查询路线----------|" << endl
			<< "|   4 -------按最少站数查询路线----------|" << endl
			<< "|   5 ----------修改地铁路线-------------|" << endl
			<< "******************************************" << endl << endl
			<< "【现有地图请参照上海地铁线路图】" << endl << endl
			<< "【如需修改线路请输入5】"
			<< "请输入1~5进行选择,其他退出:";
		char choice;
		cin >> choice;
		switch (choice)
		{
		case '1': {
			cout << "查看所有站点,请输入:1\n查看单线站点,请输入:2\n";
			int choice2;
			cin >> choice2;
			if (choice2 == 1)
				print_whole();
			else {
				cout << "请输入需要查询的线路(请输入介于0和30之间的数):  ";
				int line1;
				cin >> line1;
				if (line1 <= SIZE && line1 >= 0)
					print(line1);
				else cout << "输入错误" << endl;

			}
			cout << endl;
			break;
		}
		case '2':
			MinDist_(ga);
			cout << endl;
			break;
		case '3':
			MinChange_(gc);
			cout << endl;
			break;
		case '4':
			MinStation_(gs);
			cout << endl;
			break;
		case '5':
			mod();
			cout << endl;
			break;
		default:
			return 0;

		}
		for (int i = 0;i < SIZE;i++)
		{
			Line[i].v.clear();
		}
		M1.clear();
		M2.clear();
		V.clear();
	}
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值