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;
};
}
}
注:资料来源于网络。侵权联系删除。