一、课程设计内容
1. 课程设计的主要内容和目标
随着高校的发展,校园面积不断扩大,校园内跨区域活动频繁,为了给校内师生和校外人士办公、教学、生活等方面带来更大的便利,以及面对校园信息化建设的全面推广和迅猛发展,本系统,将通过迪杰斯特拉和弗洛伊德算法,求出所需最短路径,进一步加强数字化校园建设。
图1 西安科技大学临潼校区平面图
西安科技大学临潼校区校园导航系统主要实现以下几种功能:
1)浏览全景
显示校园的平面图,给出校园的形貌,以及各个景点的位置。
2)显示所有景点
将所有景点显示出来,包括景点编号、名称、简介等信息
3)两景点之间最短路查询
输入起点,显示该起点到其它所有景点的最短路径。
4)多景点间访问路线查询
输入起点,生成一个最小联通路径,这样游客便能以最少的行程来游览所有景点。
5)两景点间所有路径查询。
输入起点和终点,显示出这两点之间的所有路线供选择。
6)增加、删除、更新有关景点和道路的信息。(用无向网表示学校的校园景点平面图)
2.技术基础、特点及实施的条件
该项目可用C++语言实现,适于在单机环境下运行,提供VC++可视化界面。小组成员均已学习过高级语言程序设计、VisualC++基础程序应用开发,数据结构和迪杰斯特拉算法和弗洛伊德算法等课程,具有一定的开发能力。
3.人员分工
所有人都参与了项目的选题、设计、实现及测试工作,项目负责人归纳并整理小组成员在各个阶段的讨论成果,并确定最终方案。在实践阶段,按照功能模块具体分工如下:
项目负责人:李佳伟,校园导航系统中管理员管理系统增加、删除、修改部分代码编写
项目组成员:廖佳琪,校园导航系统中两景点间所有路径查询及多景点间访问路线查询部分代码编写
项目组成员:孙琪,校园导航系统中景点信息查询及两景点之间最短路查询部分代码编写
二、设计方案
1.数据结构的选择与设计
此项目来源于实际问题。随着科技的进步和时代的发展,计算机已越来越深入到人民的日常生活和工作当中,产生了极大的便利。特别是随着科技的不断发展,智能化也不再是一个名词,而是实在的、随处可见的。算法设计与分析对于程序的实现有着非常重要的作用,思路才是程序的核心。这个校园导航系统,就是利用算法设计里的图来解决,它将校园景点作为图的结点,将景点间的路径作为图的边,路径距离作为边的权值。这样一来,求两景点间最短路径的问题就抽象成了求图中一结点到另一结点的问题。这也是计算机代替人工的一个实例,也充分体现算法的重要。针对校园现代化的实现,对于来访我校的访客和新生能够更方便的了解学校的景点,便于参观,也减少导游人员的数量,于是我们编写了这个校园导航系统,为刚入学的新生或是初次到学校参观的人提供一个校园自主导航器引导他们出行。
而在功能实现过程中,校园导航模拟系统实现的几种查询功能都与图的遍历有关,所以在遍历时会用到栈或队列的数据结构,以便于算法的设计与实现。
(1)抽象数据类型定义:邻接矩阵方式存储图
数据结构定义:
struct site//定义结构体存储景点信息
struct maps //定义结构体存储景点的图
功能函数设计:
void DFS(int i) //对于选择步行的道路的深度优先搜索
void DFS1(int i) //对于选择驾车的道路进行深度优先搜索
void Search()//查询景点信息
void jingdian() //仅查看景点列表
void make_site() //建立景点及简介(数据存放)
void make_map() //创建景点间距离
void DIS(int a, int b, int c)//计算最短路径
void dijstra(int b, int a, int c) //计算两点最短路径
void mshort() //两个景点之间最短路径查询
void ashort() //两个景点间所有路径查询
int menu()//主菜单目录函数
void maps()//输入西安科技大学临潼校区地图
void Floyd()//弗洛伊德算法计算多顶点间的最短距离
void Multispot()//多景点的最佳路线规划
void addInfo(void)//添加景点
void changeInfo()//修改景点
void delInfo()//删除景点
void addload()//添加道路
void delload(void)//删除道路
void houtai1()//后台管理系统界面
void houtai()//进入后台时的验证
int main()//主函数
void Floyd_print(int s, int e)//弗洛伊德算法
void dijstra(int b,int a,int c)//迪杰斯特拉算法
(2)主函数流程
功能:启动程序,初始化数据,导入和存储数据,负责调用各个函数,完成程序的完整执行。
流程图:
图2 主函数流程图
(3)各程序模块之间的层次(调用)关系
首先创建菜单函数menu()标注出所需功能目录,其次创建Search()函数查询景点信息;接着写出最短路径函数mshort();所有路径ashort()函数;maps()函数输入西安科技大学临潼校区地图;Floyd()函数,通过弗洛伊德算法计算多顶点间的最短距离;Multispot()函数实现多景点的最佳路线规划;houtai()函数实现管理员后台添加、删除、修改功能。
最后创建主函数,调用各个功能函数,实现校园导航功能。
2.详细设计方案
抽象数据类型定义:
景点信息的结构体
struct site //景点信息
{
int number; //编号
char name[20];//名称
char infor[100];//介绍
}z;
图的结构体:
struct maps //景点的图
{
int point; //地点
int side; //边
site s[20];
int edge[20][20]; // 两个景点的距离
int edge_car[20][20];//两个景点车的距离
int e;
} m;
后台管理系统
主界面选择进入后台管理系统时,通过调用函数houtai()来判断管理员身份,账号密码通过后台存贮直接进行判断,防止其他人员进入后台管理系统。成功进入后,管理员共可实现8种功能操作.。
后台管理界面
- 景点介绍
调用函数jingdian(),输出目前所有的景点,用于对景点进行增删改后进行检查。
使用一个for循环输出景点编号和名字
- 查看校园平面图
调用函数maps(),输出在后端存储的地图。
缺点:通过其他功能对校园景点进行增删改时,地图无法进行动态修改。
- 查找任意两个景点之间的最短路径
调用函数mshort(),通过dijstra算法进行计算最短路径。
- 修改景点信息
调用函数changeinfo(),函数中首先对m.point进行判断,不为空则调用jingdian()函数,展示当前景点信息,定义两个新的变量newname和newfeatures,分别临时存储新的景点名和景点信息,从键盘获取需要修改的信息,通过strcpy()函数,将新的信息复制到m.name和m.infor中,将对应位置进行修改,则完成了一次景点信息的修改,设置标志flag进行判断是否继续进行信息修改,flag=1时继续调用函数chageinfo()进行下一次修改。
(5)增加景点信息
调用函数addinfo(),首先对m.point进行判断,若不满则继续调用jingdian()函数,展示当前景点信息,增加新的景点信息,连接其他景点并输入其道路权值,输入完成后通过strcpy()函数将新的结点信息存入m.s.nmae和m.s.infor。设置标志flag进行判断是否继续进行景点添加,flag=1时继续调用函数addinfo()进行下一次添加。
(6)删除景点信息
调用函数delinfo(),首先对m.point进行判断,若不为空则继续调用jingdian()函数,展示当前景点信息,输入将要删除的景点编号后,首先将该景点与其他景点间的道路全部置为无穷,进行初始化,设置新的int型count,对删除的道路数目进行计数,最后对景点数m.point-1,对道路数-count,完成一次删除。
(7)增加道路
调用函数addload(),对m.point和m.side进行判断,若均不为满则继续调用jingdian()函数,输出目前的所有道路m.side,新增道路,首先对两个景点之间进行判断,若m.edge.[][]不存在,则继续输入道路权值(i<200), 添加成功后,m.side+1,并存入新的信息m.edge.[][]
(8)删除道路
调用函数delload(),对m.point和m.side进行判断,若均不为空则继续调用jingdian()函数,输出目前的所有道路m.side,输入将要删除的道路编号后,判断道路是否存在,若存在则将道路道路置为无穷,进行初始化,m.side-1,道路删除完成。
(9)推出管理系统
返回上级主页面。
3.项目测试方案
项目负责人李佳伟:单元测试、集成测试
项目组成员廖佳琪:单元测试、系统重构
项目组成员孙琪:单元测试、黑盒测试
三、系统实现(附源代码)
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <cstdio>
#include <string>
#include <stack>
#include <deque>
#include<numeric>
#include<vector>
#define DELAY 982337369
#define True 1
#define False 0
using namespace std; //使用c++标准库
#define MAX 0x3f3f3f
#define PP 999999
stack<int> S;
int dis[17], vis[17];
int dist[16][16];
int path[20], path1[20][20];
const int MAXV = 1001, INF = 1000001;
bool vest[MAXV];
int nex[MAXV], d[MAXV][MAXV];
int N, M, st, ed, cnt, a = 0;
struct site //景点信息
{
int number; //编号
char name[20];//名称
char infor[100];//介绍
}z;
struct maps //景点的图
{
int point; //地点
int side; //边
site s[20];
int edge[20][20];
int edge_car[20][20];
int e;
} m;
void DFS(int i)
{
vest[i]=true;
if(i==ed)
{
cnt++;
printf("第%d条路径如下",cnt);
int k=st;
while(k!=ed)
{
printf("%d->",k);
k=nex[k];
}
printf("%d\n",k);
return;
}
for(int j=1; j<=m.point; j++)
{
if(vest[j]==false&&m.edge[i][j]!=MAX)
{
nex[i]=j;//对于路径0->1->3: nex[0]=1;nex[1]=3;
DFS(j);
vest[j]=false;
}
}
}
void DFS1(int i)
{
vest[i]=true;
if(i==ed)
{
cnt++;
printf("第%d条路径如下",cnt);
int k=st;
while(k!=ed)
{
printf("%d->",k);
k=nex[k];
}
printf("%d\n",k);
return;
}
else
printf("目的地之间没有直达的路,请选择步行。\n");
for(int j=1; j<=m.point; j++)
{
if(vest[j]==false&&m.edge_car[i][j]!=MAX)
{
nex[i]=j;//对于路径0->1->3: nex[0]=1;nex[1]=3;
DFS1(j);
vest[j]=false;
}
}
}
void Search()
{
int i, n;
printf("西安科技大学临潼校区的景点有:\n");
printf("****************\n");
for (i = 1; i <= 16; i++)
{
printf("*******%d:%s\n", m.s[i].number, m.s[i].name);
}
printf("****************\n");
while (1)
{
printf("请输入你想要查询的景点编号:\n");
printf("按0退出\n");
scanf("%d", &n);
getchar();
if (n == 0)
{
break;
}
else if (n < 1 || n>16)
{
printf("输入有误,请重新输入!!!\n\n");
continue;
}
else
{
printf("%d:%s\n", m.s[n].number, m.s[n].name);
printf("%s\n\n", m.s[n].infor);
}
}
return;
}
void jingdian()
{
int i, n;
printf("西安科技大学临潼校区的景点有:\n");
printf("****************\n");
for (i = 1; i <= 16; i++)
{
printf("*******%d:%s\n", m.s[i].number, m.s[i].name);
}
printf("****************\n");
}
void make_site()
{
int i;
for (i = 1; i <= m.point; i++)
m.s[i].number = i;
strcpy(m.s[1].name, "实验楼");
strcpy(m.s[1].infor, "学生实验场所");
strcpy(m.s[2].name, "一教");
strcpy(m.s[2].infor, "马克思主义学院,通宵自习室");
strcpy(m.s[3].name, "二教");
strcpy(m.s[3].infor, "人文与外国语学院,听力教室");
strcpy(m.s[4].name, "行政楼");
strcpy(m.s[4].infor, "校领导办公室");
strcpy(m.s[5].name, "三教");
strcpy(m.s[5].infor, "教学楼");
strcpy(m.s[6].name, "图书馆");
strcpy(m.s[6].infor, "学校图书存放处、学生自习室");
strcpy(m.s[7].name, "体育馆");
strcpy(m.s[7].infor, "室内羽毛球场以及排球场");
strcpy(m.s[8].name, "综合楼");
strcpy(m.s[8].infor, "校医院、财务处、学工部办公处");
strcpy(m.s[9].name, "第二俱乐部");
strcpy(m.s[9].infor, "开展文艺活动");
strcpy(m.s[10].name, "6、7号学生公寓");
strcpy(m.s[10].infor, "学生公寓");
strcpy(m.s[11].name, "田径场");
strcpy(m.s[11].infor, "学生课外活动场所");
strcpy(m.s[12].name, "骊绣苑");
strcpy(m.s[12].infor, "学生食堂");
strcpy(m.s[13].name, "篮球场");
strcpy(m.s[13].infor, "室外篮球比赛场地");
strcpy(m.s[14].name, "游泳馆");
strcpy(m.s[14].infor, "游泳场地");
strcpy(m.s[15].name, "学生超市");
strcpy(m.s[15].infor, "快递点,小吃一条街");
strcpy(m.s[16].name, "榴馨苑");
strcpy(m.s[16].infor, "学生食堂");
}
void make_map()
{
int i, j;
m.point = 16;
m.side = 19;
for (i = 0; i <= m.point; i++)
for (j = 0; j <= m.point; j++)
{
m.edge[i][j] = MAX;
m.edge_car[i][j] = MAX;
}
/*memset(m.edge,MAX,sizeof(m.edge));
memset(m.edge_car,MAX,sizeof(m.edge_car));
fill(m.edge[0],m.edge[0]+20*20,MAX);*/
memset(dis, MAX, sizeof(dis));
memset(vis, 0, sizeof(vis));
fill(vest, vest + MAXV, false);
fill(d[0], d[0] + MAXV * MAXV, INF);
d[0][2]=m.edge[1][3]=m.edge[3][1]=80;
d[1][2]=m.edge[2][3]=m.edge[3][2]=50;
d[2][3]=m.edge[3][4]=m.edge[4][3]=120;
d[2][4]=m.edge[3][5]=m.edge[5][3]=50;
d[4][5]=m.edge[5][6]=m.edge[6][5]=80;
d[4][7]=m.edge[5][8]=m.edge[8][5]=50;
d[4][8]=m.edge[5][9]=m.edge[9][5]=50;
d[5][9]=m.edge[6][10]=m.edge[10][6]=40;
d[7][8]=m.edge[8][9]=m.edge[9][8]=50;
d[8][9]=m.edge[9][10]=m.edge[10][9]=60;
d[3][6]=m.edge[4][7]=m.edge[7][4]=60;
d[6][9]=m.edge[7][10]=m.edge[10][7]=55;
d[6][10]=m.edge[7][11]=m.edge[11][7]=60;
d[6][13]=m.edge[7][14]=m.edge[14][7]=70;
d[9][12]=m.edge[10][13]=m.edge[13][10]=80;
d[11][12]=m.edge[12][13]=m.edge[13][12]=50;
d[12][13]=m.edge[13][14]=m.edge[14][13]=50;
d[15][16]=m.edge[12][16]=m.edge[10][16]=66;
d[16][15]=m.edge[16][12]=m.edge[16][10]=66;
d[0][2]=m.edge_car[2][4]=m.edge_car[4][2]=180;
m.edge_car[4][11]=m.edge_car[11][4]=160;
m.edge_car[11][14]=m.edge_car[14][11]=40;
m.edge_car[14][12]=m.edge_car[12][14]=120;
m.edge_car[12][8]=m.edge_car[8][12]=100;
}
void DIS(int a, int b, int c)//计算dis数组
{
memset(path, 0, sizeof(path));
int i, j, pos = 1, minn;
memset(vis, 0, sizeof(vis));
for (i = 1; i <= m.side; i++)
{
if (a == 1)
dis[i] = m.edge[b][i];
if (a == 2)
dis[i] = m.edge_car[b][i];
}
vis[b] = 1;
dis[b] = 0;
for (i = 1; i <= m.point; i++)
{
minn = MAX;
for (j = 1; j <= m.point; j++)
{
if (vis[j] == 0 && minn > dis[j])
{
minn = dis[j];
pos = j;
}
}
vis[pos] = 1;
for (j = 1; j <= 16; j++)
{
if (a == 1)
{
if (vis[j] == 0 && dis[j] > dis[pos] + m.edge[pos][j])
{
dis[j] = dis[pos] + m.edge[pos][j];
path[j] = pos;
}
}
if (a == 2)
{
if (vis[j] == 0 && dis[j] > dis[pos] + m.edge_car[pos][j])
{
dis[j] = dis[pos] + m.edge_car[pos][j];
path[j] = pos;
}
}
}
}
}
void dijstra(int b, int a, int c) //计算两点最短路径
{
DIS(a, b, c);
int x = c;
while (!S.empty())
S.pop();
// for(x=1;x<=16;x++)
// cout<<x<<" "<<path[x]<<endl;
// cout<<endl;
while (1)
{
if (x == 0)
break;
S.push(x);
x = path[x];
}
S.push(b);
if (dis[c] >= 10000)
printf("没有直达的路,请选择步行。\n");
else
{
printf("从%d到%d的最短路径为:", b, c);
while (!S.empty())
{
if (S.size() > 1)
cout << S.top() << "->";
else
cout << S.top();
S.pop();
}
printf("其最短距离为:%d", dis[c]);
}
}
void mshort()
{
int a, b, c;
printf("=====出行方式=====\n");
printf("1.步行\n");
printf("2.驾车\n");
printf("==================\n");
printf("选择出行方式\n");
scanf("%d", &a);
printf("输入起点\n");
scanf("%d", &b);
printf("输入终点\n");
scanf("%d", &c);
if ((b <= 0 && b >= 17) || (c <= 0 && c >= 17))
{
printf("输入错误");
}
else
dijstra(b, a, c);
}
void ashort() //两个景点间所有路径查询
{
int a, b, c;
printf("=====出行方式=====\n");
printf("1.步行\n");
printf("2.驾车\n");
printf("==================\n");
printf("选择出行方式\n");
scanf("%d", &a);
printf("输入起点\n");
scanf("%d", &b);
printf("输入终点\n");
scanf("%d", &c);
if ((b <= 0 && b >= 17) || (c <= 0 && c >= 17))
{
printf("输入错误");
}
else
{
st = b;
ed = c;
if(a==1)
DFS(st);
if(a==2)
DFS1(st);
}
}
int menu()
{
int n;
printf("\n");
printf(" ************欢迎使用西安科技大学临潼校区导游系统***************\n\n");
printf(" * 1.景点信息查询 *\n");
printf(" * 2.两景点之间最短路查询 *\n");
printf(" * 3.两景点间所有路径查询 *\n");
printf(" * 4.多景点间访问路线查询 *\n");
printf(" * 5.后台管理系统 *\n");
printf(" * 6.地图浏览 *\n");
printf(" * 0.退出系统 *\n");
printf(" *******************************************************\n");
printf("输入指令:\n");
scanf("%d", &n);
getchar();
return n;
}
void maps()
{
printf("\n *西安科技大学临潼校区景点地图*\n\n");
printf(" (14)游泳馆 \n");
printf(" (15)学生超市 (12)骊绣苑 (13)西篮球场◎ \n");
printf(" ◎ -------------◎(16)榴馨苑 ◎--------------| (11)田径场 \n");
printf(" |-------------| | ◎ \n");
printf(" | | / \n");
printf(" 综 (9)二俱 | | / \n");
printf(" 合 ◎ (10) | 6、7号学生公寓 / \n");
printf(" (8) 楼◎--------|---------------------◎--------------|/ \n");
printf(" \\ | | ◎ \n");
printf(" \\ | | (7) 体育馆 \n");
printf(" \\ | ◎ | \n");
printf(" \\ / |(6)图书馆 | \n");
printf(" (1)实验楼◎|-----◎-------------------------| | \n");
printf(" | | (5)三教 | \n");
printf(" | | | \n");
printf(" (2)一教◎|---------◎(3)二教--------------------------------------◎(4)行政楼 \n");
}
void Floyd()
{
int i, j, k;
for (i = 1; i <= m.point; i++)
{
for (j = 1; j <= m.point; j++)
{
dist[i][j] = m.edge[i][j];
if (i != j && dist[i][j] < PP)
{
path1[i][j] = i;
}
else
{
path1[i][j] = -1;
}
}
}
//printf("%d\n",g.n);
for (k = 1; k <= m.point; k++)
{
for (i = 1; i <= m.point; i++)
{
for (j = 1; j <= m.point; j++)
{
if (dist[i][j] > (dist[i][k] + dist[k][j]))
{
dist[i][j] = dist[i][k] + dist[k][j];
path1[i][j] = k;
}
}
}
}
return;
}//
void Floyd_print(int s, int e)
{
if (path1[s][e] == -1 || path1[s][e] == e || path1[s][e] == s)
{
return;
}
else
{
Floyd_print(s, path1[s][e]);
printf("%s->", m.s[path1[s][e]].name);
Floyd_print(path1[s][e], e);
}
}
void Multispot()
{
int vNum[20] = { 0 };
int i, j, dis1, a;
j = 1;
dis1 = 0;
printf("请输入你要游览的第%d个景点的编号(输入-1结束输入):", j);
scanf("%d", &vNum[j]);
while (vNum[j] != -1 && j <= 16)
{
printf("请输入你要游览的第%d个景点编号:", ++j);
scanf("%d", &vNum[j]);
if (vNum[j] != -1)
a = vNum[j];
if (vNum[j] == -1)
{
break;
}
}
for (i = 0; vNum[i + 1] > 0 && vNum[i + 2] > 0; i++)
{
printf("%s->", m.s[vNum[i + 1]].name);
Floyd_print(vNum[i + 1], vNum[i + 2]);
dis1 += dist[vNum[i + 1]][vNum[i + 2]];
}
printf("%s\n\n", m.s[a].name);
printf("全程总长为:%dm\n\n", dis1);
}
//添加景点
void addInfo(void) {
if (m.point >= 50)
{
printf("西科大已经满了,无法增加新景点\n");
return;
}
jingdian();
char newName[100]; char newFeatures[500];
printf("新加景点名称:\n");
scanf("%s", newName); getchar();
printf("%s景点简介?\n", newName);
scanf("%s", newFeatures); getchar();
jingdian();
int o;
printf("它旁边有几个景点?\n");
scanf("%d", &o);
int i;
for (i = 0; i < o; i++)
{
int distance;
m.s[a].number = a;
printf("输一下%s的第%d个相连的景点的编号:\n", newName, i + 1);
scanf("%d", &a);
while (a<1 || a>m.point || m.edge[a][m.point]<=200)
{
if (a<1 || a>m.point)
{
printf("输错了,编号在1到%d之间,重新输!\n", m.point);
scanf("%d", &a);
}
if (m.edge[a][m.point] <=200)
{
printf("这条路已经有了,重新输入\n");
scanf("%d", &a);
return;
}
}
printf("%s与%s之间的距离是多少?:\n", newName, m.s[a].name);
scanf("%d", &distance);
while (distance <= 0 || distance > INFINITY)
{
printf("距离输入非法了重新输入!\n");
scanf("%d", &distance);
}
m.edge[a][m.point] = m.edge[m.point][a] = distance;
}
printf("正在添加景点...\n");
strcpy(m.s[m.point++].name, newName);
strcpy(m.s[m.point - 1].infor, newFeatures);
for (i = 0; i < DELAY; i++);
printf("这个景点添加成功了!\n");
return;
}
void changeInfo() {
if (m.point <= 0)
{
printf("学校不存在,没有景点可以参观\n");
return;
}
jingdian();
m.s[a].number = a;
printf("需要修改的地方景点名称是(输入编号):\n");
scanf("%d", &a);
while (a<1 || a>m.point)
{
printf("编号输错了,从1开始到%d,你再试试别的\n", m.s);
scanf("%d", &a);
}
char newName[100];
char newFeatures[1000];
printf("这里原来叫%s,你想要改成什么?:\n", m.s[a].name);
scanf("%s", newName); getchar();
printf("简介现在是:\n%s\n你想要改成什么?:\n", m.s[a].infor);
scanf("%s", newFeatures); getchar();
printf("正在修改...\n");
strcpy(m.s[a].name, newName);
strcpy(m.s[a].infor, newFeatures);
long long int i = 0;
for (i = 0; i < 20; i++);
printf("修改完成\n");
printf("继续修改输入1,任意键退出\n");
int flag;
scanf("%d", &flag);
if (flag == True)
changeInfo();
return;
}
//删除景点
void delInfo() {
if (m.point <= 0)
{
printf("已经删没了,不能再删除!\n");
return;
}
jingdian();
printf("您要删除哪个景点?\n");
int a;
scanf("%d", &a);
while (a<1 || a>m.point)
{
printf("%d,个你都输错了,重新输入!\n", m.point);
scanf("%d", &a);
}
printf("删除的景点为:%s真的要删吗? 输入1 for sure: \n", m.s[a].name);
int flag;
scanf("%d", &flag);
if (flag == 1)
{
printf("删除景点ING\n");
int i, j;
int count = 0;
for (i = 0; i < m.point; i++)
if (m.edge[a][i] != INFINITY)
count++;
for (i = a; i < m.point; i++)
m.s[i] = m.s[i + 1];
for (i = 0; i < m.point; i++)
for (j = a; j < m.point; j++)
m.edge[i][j] = m.edge[i][j + 1];
for (i = 0; i < m.point; i++)
for (j = a; j < m.point; j++)
m.edge[j][i] = m.edge[j + 1][i];
m.point--;
m.side -= count;
}
else
return;
long long i;
for (i = 0; i < DELAY; i++);
printf("已经删完了\n,1s后回到主界面");
return;
}
void addload() {
if (m.point <= 0)
{
printf("校园里路都没有\n");
return;
}
jingdian();
if (m.side == 0)
printf("错误:目前暂无道路\n");
else
printf("目前总共有%d条道路\n", m.side);
printf("请输入道路起点和终点:\n");
int a, b;
scanf("%d %d", &a, &b);
while (a<1 || a>m.point || b<1 || b>m.point || a == b)
{
if (a == b)
printf("输入错误!\n");
else
printf("编号输入有误,最大是%d,重新输\n", m.point);
scanf("%d %d", &a, &b);
}
if (m.edge[a][b] <= 200) {
printf("%s与%s之间这条路已经有了,不要再添加!\n", m.s[a].name, m.s[b].name);
return;
}
else
{
int distance;
printf("请输入%s与%s之间道路的长度:\n", m.s[a].name, m.s[b].name);
scanf("%d", &distance);
while (distance <= 0 || distance >200)
{
printf("这个长度有问题\n");
scanf("%d", &distance);
}
printf("正在添加道路...\n");
m.edge[a][b] = m.edge[b][a] = distance;
m.side++;
long long i;
for (i = 0; i < DELAY; i++);
printf("道路添加成功!\n");
printf("1s后回到主界面");
}
return;
}
//删除道路
void delload(void) {
if (m.point <= 0)
{
printf("无任何景点,请先添加\n");
return;
}
if (m.side <= 0)
{
printf("地图中无任何道路,请先添加!\n");
return;
}
jingdian();
printf("目前总共有%d条道路\n", m.side);
printf("请输入要删除道路的两个景点编号,中间用空格隔开:\n");
int a, b;
scanf("%d %d", &a, &b);
while (a<1 || a>m.point || b<1 || b>m.point || a == b)
{
if (a == b)
printf("请勿输入两个相同编号,重新输入!\n");
else
printf("编号输入有误,两个编号都应位于1~%d之间,重新输入!\n", m.point);
scanf("%d %d", &a, &b);
}
if (m.edge[a][b] == INFINITY)
{
printf("%s与%s之间无道路!\n", m.s[a].name, m.s[b].name);
return;
}
else
{
printf("您要删除的是%s与%s的道路,确认输入1 \n", m.s[a].name, m.s[b].name);
int flag;
scanf("%d", &flag);
if (flag == 1)
{
printf("正在删除道路...\n");
m.edge[a][b] = m.edge[b][a] = INFINITY;
m.side--;
long long i;
for (i = 0; i < DELAY; i++);
printf("道路删除成功!\n");
}
else
return;
printf("1s后回到主界面");
}
return;
}
void houtai1() {
system("cls");
while (1)
{
int choose;
printf("**********后台管理系统**********\n");
printf("1.修改景点信息\n");
printf("2.增加景点信息\n");
printf("3.删除景点信息\n");
printf("4.增加道路\n");
printf("5.删除道路\n");
printf("6.退出管理系统\n");
scanf("%d", &choose);
switch (choose) {
case 1:
system("cls");
printf("修改信息:\n");
changeInfo();
break;
case 2:
system("cls");
printf("添加景点\n");
addInfo();
break;
case 3:
system("cls");
printf("删除景点信息\n");
delInfo();
break;
case 4:
system("cls");
printf("新增道路\n");
addload();
break;
case 5:
system("cls");
printf("路没了\n");
delload();
break;
case 6:
system("cls");
printf("拜拜~~\n");
return;
default:
system("cls");
printf("敲错字了吧,换个试试\n");
break;
}
}
return;
}
void houtai()
{
char x[10];
char y[10];
char q[10] = { "baotu" };
char w[10] = { "123456" };
printf("欢迎来到后台管理系统\n");
printf("账号:\n");
scanf("%s", &x);
printf("密码:\n");
scanf("%s", &y);
if (strcmp(x, q) == 0 && strcmp(y, w) == 0)
{
printf("成功进入后台管理系统!");
houtai1();
}
else
printf("密码错误!");
}
int main()
{
int n;
maps();
make_map();
make_site();
while (1)
{
n = menu();
if (n < 0 || n>7)
printf("输入错误,请重新输入\n");
else
{
if (n == 1)
Search();
else if (n == 2)
mshort();
else if (n == 3)
ashort();
else if (n == 4)
{
maps();
Floyd();
Multispot();
}
else if (n == 5)
houtai();
else if (n == 6)
maps();
else if (n == 0)
break;
}
}
}
四、测试结果(附截图及说明)
测试数据,测试输出的结果,时间复杂度分析,和每个模块设计和调试时存在问题的思考(问题是哪些?问题如何解决?),算法的改进设想。
- 主界面
图6-主界面设计图
- 第一个功能:校园景点信息介绍
图7 校园景点信息查询图
- 第二个功能:查询两景点之间的最短路径
图8 两景点之间的最短路径查询图
- 第三个功能:查询两景点之间的所有路径
图9 两景点之间的所有路径查询图
- 第四个功能:查询多景点间的访问路线,可实现游览全景的目标
图10 多景点间的访问路线查询图
- 第五个功能:后台管理系统
6.1主界面
图11 后台管理系统主界面设计图
6.2修改景点信息
图12 修改景点信息图
6.3增加景点信息
图13 增加景点信息图
6.4删除景点信息
图14 删除景点信息图
- 第六个功能:浏览校园平面图
图15 校园平面图
2.时间复杂度分析
图的深度优先遍历:
时间复杂度为o (n+e)
Floyd-Warshall算法:
时间复杂度为O (N3),空间复杂度为O (N2)。
3.遇到的问题
在测试过程中,编译时总会编译不成功。主菜单这四个模块的来构成了校园导航系统的基本组成部分,但调试的过程数据结构定义这一模块总是出现调试错误,程序的调试一度进入难题。后来由于数据结构定义模块总出错,便不再把数据结构定义设为单独的模块,而是在每一个其他模块中都进行一次编写,这样就避免了数据结构定义模块的调用错误,虽然这样使得程序变得冗余,但好在能调试成功,能使校园导航系统按照预先的设想正常运行。
- 课程设计总结
在本次的课程设计中,让我对数据结构的应用有了更深刻的认识,在后台管理系统中,小到数组字符串的比较,大到整个函数的编写,多多少少都出现了许多问题,尤其因为对c语言的不够熟练,耽误了大量的时间,在设计程序的时候,要从全局开始考虑,开始的时候出现了完成一个功能后发现在另一个功能中也需要调用部分功能,导致代码冗长,浪费空间,后面将相同的部分单独拆分成一个函数,方便各个功能之间的调用,互不影响,节约时间和空间,还有就是在测试阶段出现的各种问题,由于代码是三个人共同完成,各个编译平台之间出现了不兼容的情况,需要不断对代码进行修改,最后将代码拼接在一起花费了大量的时间,在后台测试部分,出现了对景点信息修改后地图无法更新等问题,但是由于动态绘制的操作过于繁琐,外面就将map部分直接写在后端进行输出,这也暴露出自身能力的不足,还需要不断的学习,用来充实和丰富自己,并且由于经验不足,前期我在写函数的时候没有考虑异常值的情况,导致测试的时候问题百出,还需要考虑数据存储的问题,在经历完本次的课程设计之后,我才真正的了解自身的问题,并且在本次课设中我也学习到了许多知识,期待下一次的实训机会。