前言
这段代码是大一下学习数据结构的时候写的,运用的东西不多,大体上只用到了一个地杰斯特拉的最短路径算法,其他的就是些简单的函数,以及基础的界面跳转,写的不好但是可以应付期末大作业,可直接复制使用,完整实验报告可私信, 后续会在B站发布配套的视频讲解
内容简介
此代码通过使用标准输出流实现各个界面的打印输出、运用二维数组实现无向图的端点存储、运用while循环实现页面跳转逻辑。
完整代码
#include<iostream>
#define max 100
#define infinity 10000
using namespace std;
void welcome();//开始界面
void menu();//主菜单
void message();//作者信息介绍
void mainplace();//地图地点列表
void map();//校园地图
void introduce();//主要地点简介
void position1();//地点存放函数
void dijkstra(int v0,int s);//最短路径算法函数
void menuchange();//菜单逻辑
void welcome()
{
cout<<" ________________________________"<<endl;
cout<<"| [西南科技大学导航系统] |"<<endl;
cout<<"| |"<<endl;
cout<<"| *欢迎使用西南科技大学导航系统* |"<<endl;
cout<<"|________________________________|"<<endl;
system("pause");
system("cls");
}
void menu()
{
system("cls");
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<<"|________________________________|"<<endl;
}
void menuchange()
{
int n;
while(1)
{
int v0=0,s=0;
menu();
cout<<"请输入您想要进行的操作:";
cin>>n;
switch(n)
{
case 1:
{
system("cls");
map();
cout<<"返回";
system("pause");
}break;
case 2:
{
system("cls");
mainplace();
cout<<"返回";
system("pause");
}break;
case 3:
{
system("cls");
introduce();
cout<<"返回";
system("pause");
}break;
case 4:
{
system("cls");
mainplace();
while(v0<1||v0>10)
{
cout<<"请输入您的起点:";
cin>>v0;
if(v0<1||v0>10)
{
cout<<"输入有误!请重新输入。"<<endl;
}
}
while(s<1||s>10)
{
cout<<"请输入您的终点:";
cin>>s;
if(s<1||s>10)
{
cout<<"输入有误!请重新输入。"<<endl;
}
}
system("cls");
map();
dijkstra(v0,s);
cout<<"返回主菜单";
system("pause");
}break;
case 5:
{
system("cls");
cout<<"感谢您的使用!";
exit(-1);
system("pause");
}break;
case 6:
{
system("cls");
message();
cout<<"返回";
system("pause");
}break;
default:
{
cout<<"输入不符合要求,请重新输入"<<endl;
system("pause");
}
}
}
}
void message()
{
system("cls");
cout<<" _______________________________"<<endl;
cout<<"| [西南科技大学导航系统] |"<<endl;
cout<<"| [作者信息] |"<<endl;
cout<<"| 作者:吴炫逸 |"<<endl;
cout<<"| 学号:512022 |"<<endl;
cout<<"| 专业班级:计算机2209 |"<<endl;
cout<<"|________________________________|"<<endl;
}
void mainplace()
{
cout<<" ________________________________________________"<<endl;
cout<<"| [校园主要地点] | "<<endl;
cout<<"| |"<<endl;
cout<<"| (1)西二门 (2)后花园 (3)逸夫图书馆 |"<<endl;
cout<<"| (4)北三宿舍楼 (5)科大苑食堂 (6)校友林 |"<<endl;
cout<<"| (7)中心湖 (8)科技之光广场 (9)新区体育场 |"<<endl;
cout<<"| (10)107广场 |"<<endl;
cout<<"|________________________________________________|"<<endl;
}
void map()
{
cout<<" 西南科技大学 __________________"<<endl;
cout<<" 校园地图: | |_______________________"<<endl;
cout<<" | 。_________________________ |__ "<<endl;
cout<<" ______________________________| |校友林 | |"<<endl;
cout<<"| 西二门 | | |___"<<endl;
cout<<"| 。_________________。____________|__ | |"<<endl;
cout<<"| | | 逸夫图书馆 | | |"<<endl;
cout<<"| | | | | |"<<endl;
cout<<"| | |________________。中心湖 | |"<<endl;
cout<<"| | | | | |"<<endl;
cout<<"| | 北三宿舍楼 | |__ | |"<<endl;
cout<<"| |__________。__________________| | |____________________| |"<<endl;
cout<<"| | | | | |"<<endl;
cout<<"| | |___ | __________。新区体育场 |"<<endl;
cout<<"| | | ____________| | |"<<endl;
cout<<"| |__。后花园 | | | |"<<endl;
cout<<"| | | | 科技之光广场 | |"<<endl;
cout<<"| | | 。__________________ | |"<<endl;
cout<<"| | | | |_____。107广场 |"<<endl;
cout<<"| | | | |"<<endl;
cout<<"| |___________。______| |"<<endl;
cout<<"| 科大苑食堂 __________|"<<endl;
cout<<"|_____________________________________________________________________|"<<endl;
}
void introduce()
{
while(1)
{
system("cls");
cout<<" _____________________________________"<<endl;
cout<<"| (1)中心湖 (2)逸夫图书馆 |"<<endl;
cout<<"| (3)107广场 (4)科技之光广场 |"<<endl;
cout<<"| (5)后花园 (6)校友林 |"<<endl;
cout<<"| |"<<endl;
cout<<"| 输入7 可返回主菜单 |"<<endl;
cout<<"|_____________________________________|"<<endl;
int n;
cout<<"请输入您想要查询的地点编号:";
cin>>n;
switch(n)
{
case 1:
{
system("cls");
cout<<"中心湖:"<<endl;
cout<<"中心湖又名四海湖,面积不小的一个湖,周围环绕着柳树,湖中央一个小岛,更显神秘,情侣最佳浪漫中心。"<<endl;
cout<<"返回地点列表";
system("pause");
}break;
case 2:
{
system("cls");
cout<<"逸夫图书馆:"<<endl;
cout<<"西南科技大学图书馆始建于1952年,至今已有60余年历史。60多年的丰厚沉淀,使图书馆建成了集学习、教学、研究、服务于一体的现代化大学图书馆。"<<endl;
cout<<"返回地点列表";
system("pause");
}break;
case 3:
{
system("cls");
cout<<"107广场:"<<endl;
cout<<"107广场位于西七教学楼中心,常用于组织社团招新活动以及公益互动。"<<endl;
cout<<"返回地点列表";
system("pause");
}break;
case 4:
{
system("cls");
cout<<"科技之光广场:"<<endl;
cout<<"西南科技大学科技之光广场是本校的地标性建筑之一其雕塑上由0和1的计算机语言、钉子以及齿轮组成,象征计算机学院与制造学院的光辉历程。"<<endl;
cout<<"返回地点列表";
system("pause");
}break;
case 5:
{
system("cls");
cout<<"后花园:"<<endl;
cout<<"西南科技大学后花园位于学校后山,花园里有美丽的景色以及环境优雅的餐厅。"<<endl;
cout<<"返回地点列表";
system("pause");
}break;
case 6:
{
system("cls");
cout<<"校友林:"<<endl;
cout<<"校友林位于新区体育场旁边,其中有全国各地校友会的校友石,平日里可以坐在校友林的长椅上修养身心。"<<endl;
cout<<"返回地点列表";
system("pause");
}break;
case 7:
{
system("cls");
menuchange();
system("pause");
}break;
default:
{
cout<<"输入不符合要求,请重新输入"<<endl;
system("pause");
}
}
}
}
int position[max][max];
char name[max][max]={"","西二门","后花园","逸夫图书馆","北三宿舍楼","科大苑食堂","校友林","中心湖","科技之光广场","新区体育场","107广场"};
void position1()
{
int i,j;
for(i=1;i<=10;i++)
{
for(j=1;j<=10;j++)
{
if(i==j)
{
position[i][j]=0;//同一个点之间的距离为 0
}
else position[i][j]=infinity;//初始时两点间的距离都设置成无穷大
}
}
position[1][2]=500;position[1][3]=500;position[1][4]=450;
position[2][5]=300;
position[3][6]=300;position[3][7]=100;
position[4][5]=300;position[4][7]=600;
position[5][8]=700;
position[6][7]=250;position[6][9]=800;
position[7][8]=600;position[7][9]=850;
position[8][10]=550;
position[9][10]=300;
for(i=1;i<=10;i++)
{
for(j=1;j<=10;j++)
{
position[j][i]=position[i][j];//将图变为无向图
}
}
}
void dijkstra(int v0,int s)
{
int i,j,k,v,min;
int path[max],distance[max];//distance:最优路径集合 path:当前节点所连接的之前的节点集
int flag[max],dis[max]; //flag:标记数组 dis:距离长度集合
//初始化
for(i=1;i<=10;i++)//将标记数组全部初始化为 0
{
flag[i]=0;
}
for(i=1;i<=10;i++)
{
dis[i]=position[v0][i];//将距离集合赋值为与出发点连接的边的权值
if(dis[i]<infinity)//当距离小于无穷大,则说明初始点与某节点间有路径
{
path[i]=v0;//将所有结点之前的结点设为 v0
}
}
flag[v0]=1;//此时出发点已经调用完毕,将标记数组中 v0位置的数值由 0变为 1
//求最短路径的步骤 1:每次在未标记的节点中选择与出发点相连的结点,将新找到的结点进行标记以及收录
for(i=1;i<10;i++)
{
min=infinity;
for(j=1;j<=10;j++)
{
if(flag[j]==0&&dis[j]<min)//在尚未成为最优结点的结点集中找距离不是无穷大的
{
min=dis[j];//将无穷大值赋值为两节点间的距离
k=j;//定义一个整形,存放所遍历过得结点
}
}
flag[k]=1;//将已经遍历过得结点的标记数值赋值为 1
/*求最短路径的步骤 2:计算刚加入的结点与不含标记的结点之间的距离,
如果两结点的距离之和小于不含标记的结点的自身距离,则对不含标记的结
点进行距离更新 */
for(v=1;v<=10;v++)
{
if(flag[v]==0&&dis[v]>dis[k]+position[k][v])
{
path[v]=k;
dis[v]=dis[k]+position[k][v];
}
}
}
v=s;
i=1;
while(path[v]!=v0)
{
distance[i++]=path[v];
v=path[v];
}
k=i-1;//寻找前一个点
cout<<"最短路线为:";
cout<<name[v0]<<"-->";//初始位置的名称
for(i=k;i>=1;i--)
{
cout<<name[distance[i]]<<"-->";//结点名称从后到前依次输出
}
cout<<name[s]<<endl;//最后输出目的地名称
cout<<"全程"<<dis[s]<<"米"<<endl;
}
int main()
{
position1();
welcome();
menu();
menuchange();
}
代码解读
基本函数
void welcome();//开始界面
void menu();//主菜单
void message();//作者信息介绍
void mainplace();//地图地点列表
void map();//校园地图
void introduce();//主要地点简介
void position1();//地点之间的距离
void dijkstra(int v0,int s);//最短路径
void menuchange();//菜单逻辑
这里就是整个导航系统所用的函数,各个函数名后面已经给出了相应功能的介绍,接下来为各位逐个分析各个函数的功能实现以及用途
开始界面
void welcome()
{
cout<<" ________________________________"<<endl;
cout<<"| [西南科技大学导航系统] |"<<endl;
cout<<"| |"<<endl;
cout<<"| *欢迎使用西南科技大学导航系统* |"<<endl;
cout<<"|________________________________|"<<endl;
system("pause");
system("cls");
}
此代码用到的是非常简单的输出流,并搭配system()函数实现界面暂停以及清空操作,其中system()函数包含在头文件 “stdlib.h” 中
主菜单
void menu()
{
system("cls");
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<<"|________________________________|"<<endl;
}
此功能函数和欢迎界面的功能函数实现效果大体相同,同样只使用到了标准输出流以及system()函数中的清空函数,此处没有使用暂停函数是因为我将暂停函数放在菜单逻辑函数中了,这一点是不影响整体使用的,如果想要将暂停函数放在各个分函数中也是可以的
作者信息介绍
void message()
{
system("cls");
cout<<" _______________________________"<<endl;
cout<<"| [西南科技大学导航系统] |"<<endl;
cout<<"| [作者信息] |"<<endl;
cout<<"| 作者:吴炫逸 |"<<endl;
cout<<"| 学号:512022 |"<<endl;
cout<<"| 专业班级:计算机2209 |"<<endl;
cout<<"|________________________________|"<<endl;
}
讲解同上
地图地点列表
void mainplace()
{
cout<<" ________________________________________________"<<endl;
cout<<"| [校园主要地点] | "<<endl;
cout<<"| |"<<endl;
cout<<"| (1)西二门 (2)后花园 (3)逸夫图书馆 |"<<endl;
cout<<"| (4)北三宿舍楼 (5)科大苑食堂 (6)校友林 |"<<endl;
cout<<"| (7)中心湖 (8)科技之光广场 (9)新区体育场 |"<<endl;
cout<<"| (10)107广场 |"<<endl;
cout<<"|________________________________________________|"<<endl;
}
讲解同上
校园地图
void map()
{
cout<<" 西南科技大学 __________________"<<endl;
cout<<" 校园地图: | |_______________________"<<endl;
cout<<" | 。_________________________ |__ "<<endl;
cout<<" ______________________________| |校友林 | |"<<endl;
cout<<"| 西二门 | | |___"<<endl;
cout<<"| 。_________________。____________|__ | |"<<endl;
cout<<"| | | 逸夫图书馆 | | |"<<endl;
cout<<"| | | | | |"<<endl;
cout<<"| | |________________。中心湖 | |"<<endl;
cout<<"| | | | | |"<<endl;
cout<<"| | 北三宿舍楼 | |__ | |"<<endl;
cout<<"| |__________。__________________| | |____________________| |"<<endl;
cout<<"| | | | | |"<<endl;
cout<<"| | |___ | __________。新区体育场 |"<<endl;
cout<<"| | | ____________| | |"<<endl;
cout<<"| |__。后花园 | | | |"<<endl;
cout<<"| | | | 科技之光广场 | |"<<endl;
cout<<"| | | 。__________________ | |"<<endl;
cout<<"| | | | |_____。107广场 |"<<endl;
cout<<"| | | | |"<<endl;
cout<<"| |___________。______| |"<<endl;
cout<<"| 科大苑食堂 __________|"<<endl;
cout<<"|_____________________________________________________________________|"<<endl;
}
讲解仍然同上。但此处需要注意的一点,因为是校园导航系统,所以校园地图中地点的分配不要太随意,如果想要视觉效果比较好的话,两个地点的视觉距离与下面 地点之间的距离函数 中的数据要相对符合
在建立地图的时候最好用格子纸提前手绘一张样图,将校园的各个地点放置在两线交叉的地方,这样可以更好的确定其坐标,同时将可直接到达的两个地点用线连接起来,并 根据比例设置两点间距离 以及 对各个地点进行编号。
注意上述手绘草图这个操作一定不要省略,其一是后面的代码有了这个图的基础会有一个很清晰的思路,其二是这个图可以放在实验报告里嘛
主要地点简介
void introduce()
{
while(1)
{
system("cls");
cout<<" _____________________________________"<<endl;
cout<<"| (1)中心湖 (2)逸夫图书馆 |"<<endl;
cout<<"| (3)107广场 (4)科技之光广场 |"<<endl;
cout<<"| (5)后花园 (6)校友林 |"<<endl;
cout<<"| |"<<endl;
cout<<"| 输入7 可返回主菜单 |"<<endl;
cout<<"|_____________________________________|"<<endl;
int n;
cout<<"请输入您想要查询的地点编号:";
cin>>n;
switch(n)
{
case 1:
{
system("cls");
cout<<"中心湖:"<<endl;
cout<<"中心湖又名四海湖,面积不小的一个湖,周围环绕着柳树,湖中央一个小岛,更显神秘,情侣最佳浪漫中心。"<<endl;
cout<<"返回地点列表";
system("pause");
}break;
case 2:
{
system("cls");
cout<<"逸夫图书馆:"<<endl;
cout<<"西南科技大学图书馆始建于1952年,至今已有60余年历史。60多年的丰厚沉淀,使图书馆建成了集学习、教学、研究、服务于一体的现代化大学图书馆。"<<endl;
cout<<"返回地点列表";
system("pause");
}break;
case 3:
{
system("cls");
cout<<"107广场:"<<endl;
cout<<"107广场位于西七教学楼中心,常用于组织社团招新活动以及公益互动。"<<endl;
cout<<"返回地点列表";
system("pause");
}break;
case 4:
{
system("cls");
cout<<"科技之光广场:"<<endl;
cout<<"西南科技大学科技之光广场是本校的地标性建筑之一其雕塑上由0和1的计算机语言、钉子以及齿轮组成,象征计算机学院与制造学院的光辉历程。"<<endl;
cout<<"返回地点列表";
system("pause");
}break;
case 5:
{
system("cls");
cout<<"后花园:"<<endl;
cout<<"西南科技大学后花园位于学校后山,花园里有美丽的景色以及环境优雅的餐厅。"<<endl;
cout<<"返回地点列表";
system("pause");
}break;
case 6:
{
system("cls");
cout<<"校友林:"<<endl;
cout<<"校友林位于新区体育场旁边,其中有全国各地校友会的校友石,平日里可以坐在校友林的长椅上修养身心。"<<endl;
cout<<"返回地点列表";
system("pause");
}break;
case 7:
{
system("cls");
menuchange();
system("pause");
}break;
default:
{
cout<<"输入不符合要求,请重新输入"<<endl;
system("pause");
}
}
}
}
这个函数里面增加了switch()语法,整体来说还是比较容易的,需要注意,case:后的数字与次函数前面的列表一致即可,并且此处的返回主菜单我采用的是在一次调用主菜单的方式实现的
重要函数
地点存放函数
提前在头文件处定义好常量max的大小,其大小可以随意设定,在这里我设定的是100,但是注意不要太大,防止和迪杰斯特拉函数中的无穷大搞混
#define max 100
首先定义两个二维数组,整形二维数组存放两个地点间的距离 、字符二维数组存放起始地点以及目标地点的名称,注意 :name数组存储单元的位置与接下来两点间距离初始化有对应关系,所以建议初始化name数组的时候,存储单元的位置与草图的地点编号相统一,例如在之前的草图上我将西二门编号为1号,所以将name数组的第1个存储单元初始化为西二门;又因为草图上没有编号0,所以name数组的第0个存储单元初始化为空。
int position[max][max];
char name[max][max]={"","西二门","后花园","逸夫图书馆","北三宿舍楼","科大苑食堂","校友林","中心湖","科技之光广场","新区体育场","107广场"};
接下来我会将这个函数的实现进行分段讲解。
void position1()
{
int i,j;
for(i=1;i<=10;i++)
{
for(j=1;j<=10;j++)
{
if(i==j)
{
position[i][j]=0;//同一个点之间的距离为 0
}
else position[i][j]=infinity;//初始时两点间的距离都设置成无穷大
}
}
position[1][2]=500;position[1][3]=500;position[1][4]=450;
position[2][5]=300;
position[3][6]=300;position[3][7]=100;
position[4][5]=300;position[4][7]=600;
position[5][8]=700;
position[6][7]=250;position[6][9]=800;
position[7][8]=600;position[7][9]=850;
position[8][10]=550;
position[9][10]=300;
for(i=1;i<=10;i++)
{
for(j=1;j<=10;j++)
{
position[j][i]=position[i][j];//将图变为无向图
}
}
}
定义好数组之后,就要实现图的距离的基本初始化,通过两个for循环的嵌套对二维数组的i和j依次遍历,并进行判断如果i和j的大小相等就代表是同一个点,即两点间的距离为0,所以二维数组的大小也为0;如果i和j的大小不同,就说明不是同一个点,即两点间距离不为0,在这里我们先将二维数组的大小设置为无穷大。(注意:因为程序中并没有非常大的数据,所以在这里无穷大用一个较大的数代替即可,为了代码编写方便,这个数可以在头文件处定义为常量)
for(i=1;i<=10;i++)
{
for(j=1;j<=10;j++)
{
if(i==j)
{
position[i][j]=0;//同一个点之间的距离为 0
}
else position[i][j]=infinity;//初始时两点间的距离都设置成无穷大
}
}
接下来将不为零的两个地点的距离进行存储,这里就要搭配之前画的草图进行存放了。例如:1号地点对应的是西二门,二号地点对应的是后花园,通过手绘草图可以看到西二门和后花园设定的距离为500,所以令position[1][2]=500;其他距离依此规律进行存储,需要注意的一点是, 如果两地点之间并没有直接连接则无须存储,此处只存储直接相连的两地点间距离,例如逸夫图书馆和科大苑食堂没有直接相连,就不用存储他们两个之间的距离了
position[1][2]=500;position[1][3]=500;position[1][4]=450;
position[2][5]=300;
position[3][6]=300;position[3][7]=100;
position[4][5]=300;position[4][7]=600;
position[5][8]=700;
position[6][7]=250;position[6][9]=800;
position[7][8]=600;position[7][9]=850;
position[8][10]=550;
position[9][10]=300;
通过常识我们可以知道,导航系统中的图为无向图,即从a到b和从b到a是相通的并且两者的距离是一样的,所以通过两个for循环,将图转变为无向图
for(i=1;i<=10;i++)
{
for(j=1;j<=10;j++)
{
position[j][i]=position[i][j];//将图变为无向图
}
}
最短路径算法
void dijkstra(int v0,int s)
{
int i,j,k,v,min;
int path[max],distance[max];//distance:最优路径集合 path:当前节点所连接的之前的节点集
int flag[max],dis[max]; //flag:标记数组 dis:距离长度集合
//初始化
for(i=1;i<=10;i++)//将标记数组全部初始化为 0
{
flag[i]=0;
}
for(i=1;i<=10;i++)
{
dis[i]=position[v0][i];//将距离集合赋值为与出发点连接的边的权值
if(dis[i]<infinity)//当距离小于无穷大,则说明初始点与某节点间有路径
{
path[i]=v0;//将所有结点之前的结点设为 v0
}
}
flag[v0]=1;//此时出发点已经调用完毕,将标记数组中 v0位置的数值由 0变为 1
//求最短路径的步骤 1:每次在未标记的节点中选择与出发点相连的结点,将新找到的结点进行标记以及收录
for(i=1;i<10;i++)
{
min=infinity;
for(j=1;j<=10;j++)
{
if(flag[j]==0&&dis[j]<min)//在尚未成为最优结点的结点集中找距离不是无穷大的
{
min=dis[j];//将无穷大值赋值为两节点间的距离
k=j;//定义一个整形,存放所遍历过得结点
}
}
flag[k]=1;//将已经遍历过得结点的标记数值赋值为 1
/*求最短路径的步骤 2:计算刚加入的结点与不含标记的结点之间的距离,
如果两结点的距离之和小于不含标记的结点的自身距离,则对不含标记的结
点进行距离更新 */
for(v=1;v<=10;v++)
{
if(flag[v]==0&&dis[v]>dis[k]+position[k][v])
{
path[v]=k;
dis[v]=dis[k]+position[k][v];
}
}
}
v=s;
i=1;
while(path[v]!=v0)
{
distance[i++]=path[v];
v=path[v];
}
k=i-1;//寻找前一个点
cout<<"最短路线为:";
cout<<name[v0]<<"-->";//初始位置的名称
for(i=k;i>=1;i--)
{
cout<<name[distance[i]]<<"-->";//结点名称从后到前依次输出
}
cout<<name[s]<<endl;//最后输出目的地名称
cout<<"全程"<<dis[s]<<"米"<<endl;
}
结语
如有需要此代码相关 实验报告 的可私信,后续会在B站发布配套的视频讲解
持续更新,未完待续