别找了,完整代码在这||校园导游咨询系统

juster数据结构实验2:校园导游咨询系统(附完整代码)



1、项目概述

1.1项目目标和主要内容

项目目标:设计一个校园导游程序,为来访的客人提供各种信息查询服务。
开发平台:Visual Studio 2022 x64
语言:C++

2.1【测试数据】

以江苏科技大学长山校区为例。

3.1【实现提示】

一般情况下,校园的道路是双向通行的,可设校园平面图是一个无向网.顶点和边均含有相关信息.

4.1项目的主要功能

(1)设计你所在学校的校园平面图,所含景点不少于10个.以图中顶点表示校内各景点,存放景点名称、代号、简介 等信息;以边表示路径,存放路径长度等相关信息。
(2)为来访客人提供图中任意景点相关信息的查询。
(3)为来访客人提供图中任意景点的问路查询,即查询任意两个景点之间的一条最短的简单路径。

在这里插入图片描述
图2-1:景观图

在这里插入图片描述

图2-2:简略图

2、项目设计

2.1项目流程图

在这里插入图片描述

图2-3:项目流程图

2.2关键算法分析

算法:Floyd算法
算法功能:搜索最优路径

算法介绍:Floyd算法(Floyd-Warshall algorithm)又称为弗洛伊德算法、插点法,是解决给定的加权图中顶点间的最短路径的一种算法,可以正确处理有向图或负权的最短路径问题,同时也被用于计算有向图的传递闭包。该算法名称以创始人之一、1978年图灵奖获得者、斯坦福大学计算机科学系教授罗伯特·弗洛伊德命名。
适用范围:无负权回路即可,边权可正可负,运行一次算法即可求得任意两点间最短路。

优缺点:

Floyd算法适用于APSP(AllPairsShortestPaths),是一种动态规划算法,稠密图效果最佳,边权可正可负。此算法简单有效,由于三重循环结构紧凑,对于稠密图,效率要高于执行|V|次Dijkstra算法。

优点:容易理解,可以算出任意两个节点之间的最短距离,代码编写简单
缺点:时间复杂度比较高,不适合计算大量数据。
时间复杂度:O(n3);空间复杂度:O(n2);

任意节点i到j的最短路径两种可能:

直接从i到j;
从i经过若干个节点k到j。
map(i,j)表示节点i到j最短路径的距离,对于每一个节点k,检查map(i,k)+map(k,j)小于map(i,j),如果成立,map(i,j) = map(i,k)+map(k,j);遍历每个k,每次更新的是除第k行和第k列的数。

3、程序运行结果

在这里插入图片描述

图2-4 项目运行图

4、总结

4.1 项目的难点和关键点

1.求最短路径判断合适算法及编写相关代码。
2.Floyd算法的理解。

4.2 心得体会

1.学习Floyd算法并运用。
2.可以拓展学习其他最短路径算法,如
① dijkstra算法,最经典的单源最短路径算法
② bellman-ford算法,允许负权边的单源最短路径算法
③ spfa,是bellman-ford+队列优化,其实和bfs的关系更密一点

5、参考文献

https://blog.csdn.net/qq_56004086/article/details/124842558?spm=1001.2014.3001.5502
https://blog.csdn.net/ytuyzh/article/details/88617987
以及其他网络资源

6、项目源码

#include <stdio.h>
#include <windows.h>
#include<iostream>//setw
#include <iomanip>//cout
#include<fstream>  //使用输入文件流ifstream
#include <string.h>//在使用字符数组的时候需要用到
#include <stdlib.h>//包含system等系统调用
#include <conio.h>//定义了通过键盘产生的对应的操作
using namespace std;

#define MAXVEX 13     //最大顶点个数 
#define INFINITY 3276//图的矩阵中A(i,i)记为0,若没有通路,记为INFINITY = 32762
int PathMatirx[MAXVEX][MAXVEX];
int ShortPath[MAXVEX][MAXVEX];

//结点的结构体--代表实际中的景点
typedef struct {
	int Num;//景点的编号
	string name;       //校园景点名
	string info;    //校园景点的描述信息
}VextexType;

//邻接矩阵的数据类型 
typedef struct {
	int AdjMatrix[MAXVEX][MAXVEX]; //用二维数组来存放邻接矩阵 
	VextexType vex[MAXVEX];    //存放顶点信息
	int vexnum;		//顶点数 
	int arcnum;     //边数 
}MGraph;


/*
主要函数及其功能介绍
void InitGraph();//初始化无向图
void Menu();//向用户显示菜单
void PrintAllInfo();//打印所有景点的信息
void MapDisplay();//显示地图函数
void ShortestPathOfAnyTwo(MGraph G);//查询任意两景点之间最短路径
void Floyd();//弗洛伊德算法求最短路径函数
void AddArc(MGraph G);//增加边<v,w>
DelVertex(MGraph G);//删去顶点v和所有与之关联的边
DelArc(MGraph G);//删去边<v,w>
UpdateIifo();//更新景点信息
*/
void InitGraph(MGraph& G) {
	int i = 0, j = 0;
	G.vexnum = 13;
	G.arcnum = 19;
	for (int i = 0; i < 13; i++) {
		G.vex[i].Num = i + 1;//第1号景点到第13号景点
	}
	G.vex[0].name = "行政楼";
	G.vex[0].name, "行政楼";
	G.vex[0].info = "老师办公,校领导开会的地方";
	G.vex[1].name = "计算机学院楼";
	G.vex[1].info = "有很多需要用到的计算机实验室";
	G.vex[2].name = "图书馆";
	G.vex[2].info = "学习的地方";
	G.vex[3].name = "文理大楼";
	G.vex[3].info = "江科大地标建筑";
	G.vex[4].name = "东苑食堂";
	G.vex[4].info = "菜肴很多,三楼有小龙虾";
	G.vex[5].name = "明德楼";
	G.vex[5].info = "很适合自习,靠经操场,学累了可以去放松一下";
	G.vex[6].name = "西操场";
	G.vex[6].info = "锻炼身体的好地方";
	G.vex[7].name = "文体中心";
	G.vex[7].info = "有羽毛球场,篮球场,乒乓球场等等,在这里可以尽情释放自己,挥洒汗水";
	G.vex[8].name = "东操场";
	G.vex[8].info = "适合傍晚散步,看夕阳,野营等等";
	G.vex[9].name = "笃学楼";
	G.vex[9].info = "楼如其名,笃学明德,经世致用";
	G.vex[10].name = "西苑食堂";
	G.vex[10].info = "三楼有少数民族餐厅,一楼二楼的饭菜都很好吃";
	G.vex[11].name = "48栋学生宿舍";
	G.vex[11].info = "学生晚上休息睡觉的地方";
	G.vex[12].name = "校医院";
	G.vex[12].info = "如果你感觉到身体不适,请来这里";
	//注意无向图是对称的
	for (int i = 0; i < 13; i++) {
		for (int j = 0; j < 13; j++) {
			G.AdjMatrix[i][j] = INFINITY;
			G.AdjMatrix[0][1] = G.AdjMatrix[1][0] = 10;
			G.AdjMatrix[0][2] = G.AdjMatrix[2][0] = 20;
			G.AdjMatrix[1][3] = G.AdjMatrix[3][1] = 5;
			G.AdjMatrix[1][9] = G.AdjMatrix[9][1] = 13;
			G.AdjMatrix[2][9] = G.AdjMatrix[9][2] = 6;
			G.AdjMatrix[2][4] = G.AdjMatrix[4][2] = 8;
			G.AdjMatrix[3][5] = G.AdjMatrix[5][3] = 7;
			G.AdjMatrix[3][9] = G.AdjMatrix[9][3] = 10;
			G.AdjMatrix[4][9] = G.AdjMatrix[9][4] = 8;
			G.AdjMatrix[4][8] = G.AdjMatrix[8][4] = 12;
			G.AdjMatrix[5][6] = G.AdjMatrix[6][5] = 5;
			G.AdjMatrix[5][10] = G.AdjMatrix[10][5] = 10;
			G.AdjMatrix[6][10] = G.AdjMatrix[10][6] = 10;
			G.AdjMatrix[6][7] = G.AdjMatrix[7][6] = 8;
			G.AdjMatrix[6][12] = G.AdjMatrix[12][6] = 15;
			G.AdjMatrix[7][9] = G.AdjMatrix[9][7] = 15;
			G.AdjMatrix[7][12] = G.AdjMatrix[12][7] = 20;
			G.AdjMatrix[8][9] = G.AdjMatrix[9][8] = 15;
			G.AdjMatrix[10][11] = G.AdjMatrix[11][10] = 7;
			G.AdjMatrix[10][12] = G.AdjMatrix[12][10] = 15;
			G.AdjMatrix[11][12] = G.AdjMatrix[12][11] = 17;
		}
	}
}

void MapDisplay() {
	system("mspaint Cloud_Picture.jpg");//使用Windows自带的画板打开校园云图
	system("mspaint Plane_Figure.png");//使用Windows自带的画板打开校园平面图
}

void Menu() {
	system("cls");//清屏
	cout << endl;
	cout << "|----------------------------欢迎来到江苏科技大学-------------------------------\n";
	cout << "|---------------------------校园导游系统功能菜单图------------------------------\n";
	cout << "|*******************************************************************************\n";
	cout << "|      1.显示江苏科技大学云图和景点平面图     2. 校园景点一览                   \n";
	cout << "|      3.显示任意两个景点间的最短路径         4. 增加某个景点                   \n";
	cout << "|      5.删除某个景点                         6.增加某条道路                    \n";
	cout << "|      7.删除某条道路                         8.更新景点信息                    \n";
	cout << "|      9.查看邻接矩阵                         10.查询从某个景点开始最短路程游历完所有景点 \n";
	cout << "|      0.退出                                                                   \n";
	cout << "|*******************************************************************************\n";
	cout << endl;
}

void PrintAllInfo(MGraph& G) {
	cout.setf(ios::left, ios::adjustfield);
	cout << setw(10) << "编号" << setw(15) << "名称" << "简介" << endl;
	for (int i = 0; i < G.vexnum; i++) {
		cout << setw(10) << G.vex[i].Num << setw(15) << G.vex[i].name << G.vex[i].info << endl;
	}
}


/*
Floyd算法(弗洛伊德算法)求最短路径:
两个准备的二维数组:
int PathMatirx[MAXVEX][MAXVEX];//记录对应点的最小路径的前驱点,例如p(1,3) = 2 说明顶点1到顶点3的最小路径要经过2
int ShortPath[MAXVEX][MAXVEX];//记录顶点间的最小路径值
*/
void Floyd(MGraph& G) {
	//对Floyd的两个数组进行初始化
	for (int i = 0; i < G.vexnum; i++) {
		for (int j = 0; j < G.vexnum; j++) {
			PathMatirx[i][j] = j;
			ShortPath[i][j] = G.AdjMatrix[i][j];
		}
	}
	for (int k = 0; k < G.vexnum; k++) {
		for (int v = 0; v < G.vexnum; v++) {
			for (int w = 0; w < G.vexnum; w++) {
				if (ShortPath[v][w] > ShortPath[v][k] + ShortPath[k][w]) {
					//更新最短路径
					ShortPath[v][w] = ShortPath[v][k] + ShortPath[k][w];
					//更新路径中间经过的节点
					PathMatirx[v][w] = PathMatirx[v][k];
				}
			}
		}
	}
}

void ShortestPathOfAnyTwo(MGraph& G) {
	int start, end, k;
	bool flag1 = false;
	bool flag2 = false;
	cout << "请您输入要查询最短路径的两个不同的景点的编号!" << endl;
	cout << "请您输入起点景点的编号:";
	cin >> start;
	cout << "请您输入终点景点的编号:";
	cin >> end;
	if (start == end) {
		cout << "对不起!您所输入的两个景点的编号一样,请重新输入" << endl;
	}
	for (int i = 0; i < G.vexnum; i++) {
		if (start == G.vex[i].Num) {
			flag1 = true;
		}
		if (end == G.vex[i].Num) {
			flag2 = true;
		}
	}
	if (!(flag1 == true && flag2 == true)) {
		cout << "您输入的两个景点中有不存在的情况,请重新输入" << endl;
	}
	cout << "从景点 " << G.vex[start - 1].name << " 到景点 " << G.vex[end - 1].name << "的最短路径长度为:" << ShortPath[start][end] << endl;
	cout << "具体路径为:" << endl;
	k = PathMatirx[start][end];
	cout << start << "--->";
	while (k != end) {
		cout << k << "--->";
		k = PathMatirx[k][end];
	}
	cout << end << endl;
}


void DelArc(MGraph& G) {
	int start;
	int end;//start和end都是从1开始
	cout << "请输入您想删除的边的起始结点" << endl;
	cin >> start;
	if (start < 1 || start>G.vexnum) {
		cout << "您输入的结点不存在" << endl;
		return;
	}
	cout << "请输入您想删除的边的结束结点" << endl;
	cin >> end;
	if (end < 1 || end>G.vexnum) {
		cout << "您输入的结点不存在" << endl;
		return;
	}
	if (start == end) {
		cout << "当前输入的两个节点相同" << endl;
		return;
	}
	if (G.AdjMatrix[start - 1][end - 1] == INFINITY) {
		cout << G.AdjMatrix[start - 1][end - 1] << endl;
		cout << "当前两节点之间无边" << endl;
		return;
	}
	G.AdjMatrix[start - 1][end - 1] = G.AdjMatrix[end - 1][start - 1] = INFINITY;
	G.arcnum--;
	cout << "删除成功" << endl;
}

void DelVertex(MGraph& G) {
	int number;
	cout << "请输入您想删去的结点的编号" << endl;
	cin >> number;
	if (number<1 || number>G.vexnum) {
		cout << "您的输入有误,请重新输入" << endl;
	}
	int count = 0;
	//删去顶点v和所有与之关联的边
	for (int i = 0; i < G.vexnum; i++) {
		if (!(G.AdjMatrix[i][number - 1] == INFINITY)) {
			G.AdjMatrix[i][number - 1] = G.AdjMatrix[number - 1][i] = INFINITY;
			count++;
		}
	}
	G.vex[number - 1].name = "NULL";
	G.vex[number - 1].info = "NULL";
	PrintAllInfo(G);
}

void AddVertex(MGraph& G) {
	string name;
	string info;
	cout << "请您输入您要增加的景点的名称" << endl;
	cin >> name;
	for (int i = 0; i < G.vexnum; i++) {
		if (name == G.vex[i].name) {
			cout << "您要增加的景点已经存在!" << endl;
			return;
		}
	}

	cout << "请您输入您要增加的景点的简介" << endl;
	cin >> info;
	int n = G.vexnum;
	G.vex[n].Num = G.vexnum;
	G.vex[n].name = "name";
	G.vex[n].info = "info";
	G.vexnum++;
	cout << "已成功增加景点!" << endl;
	cout << endl;
}

void AddArc(MGraph& G) {
	int start;
	int end;//start和end都是从1开始
	cout << "请输入您想增加的边的起始结点" << endl;
	cin >> start;
	if (start < 1 || start>G.vexnum) {
		cout << "您输入的结点不存在" << endl;
		return;
	}
	cout << "请输入您想增加的边的结束结点" << endl;
	cin >> end;
	if (end < 1 || end > G.vexnum) {
		cout << "您输入的结点不存在" << endl;
		return;
	}
	if (start == end) {
		cout << "当前输入的两个节点相同" << endl;
		return;
	}
	if (!(G.AdjMatrix[start - 1][end - 1] == INFINITY)) {
		cout << "当前两节点之间已有边" << endl;
		return;
	}
	int weight;
	cout << "请输入您想增加的边的权重" << endl;
	cin >> weight;
	G.AdjMatrix[start - 1][end - 1] = G.AdjMatrix[end - 1][start - 1] = weight;
	cout << "增加成功" << endl;
	G.arcnum++;
}

void UpdateIifo(MGraph& G) {
	//更新景点信息
	int number;
	string info;
	string name;
	cout << "请输入您想更新的景点的编号" << endl;
	cin >> number;
	if (number<1 || number>G.vexnum) {
		cout << "您的输入有误,请重新输入" << endl;
		return;
	}
	cout << "请输入景点新的信息" << endl;
	cin >> info;
	cout << info << endl;
	G.vex[number - 1].info = info;
	cin >> name;
	cout << name << endl;
	G.vex[number - 1].name = name;
	cout << "修改成功" << endl;
	PrintAllInfo(G);
}

void PrintAdj(MGraph& G) {
	for (int i = 0; i < G.vexnum; i++) {
		for (int j = 0; j < G.vexnum; j++) {
			cout << G.AdjMatrix[i][j] << " ";
		}
		cout << endl;
	}
}

//prim算法求最小生成树
void Prim(MGraph& G) {
	cout << "请输入您想从几号景点" << endl;
	int choice;
	cin >> choice;
	struct {
		int adjvex;
		int lowcost;
	}closedge[MAXVEX];
	int i, e, k, m, min;
	closedge[choice].lowcost = 0;
	for (i = 0; i < G.vexnum; i++)
		if (i != choice - 1)
		{
			closedge[i].adjvex = choice - 1;
			closedge[i].lowcost = G.AdjMatrix[choice - 1][i];
		}
	for (e = 0; e < G.vexnum - 1; e++) {
		min = INFINITY;
		for (k = 0; k < G.vexnum; k++) {
			if (closedge[k].lowcost != 0 && closedge[k].lowcost < min) {
				m = k;
				min = closedge[k].lowcost;
			}
		}
		printf("从%s<------>%s:%dm\n", G.vex[closedge[m].adjvex].name, G.vex[m].name, closedge[m].lowcost);
		closedge[m].lowcost = 0;
		//当m加入后,更新closedge数组信息
		for (i = 0; i < G.vexnum; i++) {
			if (i != m && G.AdjMatrix[m][i] < closedge[i].lowcost) {
				closedge[i].lowcost = G.AdjMatrix[m][i];
				closedge[i].adjvex = m;
			}
		}
	}
}
int main() {
	cout << "欢迎来到江苏科技大学长山校区" << endl;
	MGraph G;
	InitGraph(G);//初始化
	Menu();//用户看到菜单
	bool flag = true;
	while (flag) {
		cout << "请输入您的选择:" << endl;
		int choice;
		cin >> choice;
		switch (choice) {
		case 1:
			MapDisplay();
			break;
		case 2:
			PrintAllInfo(G);
			break;
		case 3:
			Floyd(G);
			ShortestPathOfAnyTwo(G);
			break;
		case 4:
			AddVertex(G);
			break;
		case 5:
			DelVertex(G);
			break;
		case 6:
			AddArc(G);
			break;
		case 7:
			DelArc(G);
			break;
		case 8:
			UpdateIifo(G);
			break;
		case 9:
			PrintAdj(G);
			break;
		case 10:
			Prim(G);
			break;
		case 0:
			cout << "感谢您的使用,再见" << endl;
			flag = false;
			break;
		default:
			cout << "您的输入有误,请重新输入" << endl;
		};
	}
}


注:资料来源于网络。侵权联系删除。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值