这是本科数据结构课设时设计的一个校园导游咨询系统,包含界面可视化,功能丰富,欢迎参考,觉得可以的话,可以点个赞,谢谢!
需求分析
一、课题内容分析
-
设计内容:设计一个**大学校园导游程序,为来访的客人提供各种信息查询服务。
-
具体功能有:
-
(1)设计**大学的校园平面图,以图中顶点表示校内各景点,存放景点名称、代号、简介等信息;以边表示路径,存放路径长度等相关信息。
-
(2)为来访客人提供图中任意景点相关信息的查询。
-
(3)为来访客人提供图中任意景点的问路查询,即查询任意两相景点之间的一条最短的简单路径。
-
(4)提供图中任意景点问路查询,即求任意两个景点之间的所有路径。
-
(5)提供校园图中多个景点的最佳访问路线查询,即求途经这多个景点的最佳路径。
二、设计思路
- 校园导游咨询系统模型是由景点和景点之间的路径组成的,所以可以用图的数据结构来实现。用图的结点代表景点,用图的边代表景点之间的路径。首先设计一个图类,结点值代表景点信息,边的权值代表景点间的距离。结点值及边的权值使用文件存储,通过读取文件来获取景点信息和景点之间的距离。计算任意两景点之间的最短路径可以使用Floyd算法实现,使用深度优先遍历算法来实现两景点之间的所有路径。最后用switch选择语句来执行不同编号的功能。
三、系统模块划分
四、需求分析
3.1 所需知识点
- (1) 图的各种遍历算法
- (2) 单源最短路径(Dijkstra算法)
- (3) 所有顶点对的最短路径(Floyd算法)
- (4) 图的基本存储结构(邻接矩阵)
- (5) 文件的读取存储操作
- (6) 界面交互
3.2 数据结构
- 本课题用到的数据结构是图的数据结构,其中用到的是图的邻接矩阵存储结构。
typedef struct { /*存放景点信息的结构体*/
int num; /*景点代号*/
char name[20]; /*景点名称*/
char intro[200]; /*景点简介*/
}vertextype;
typedef int edgtype; /*权值类型*/
typedef struct { /*校园景点图结构体*/
vertextype vexs[M]; /*顶点信息域*/
edgtype edge[M][M]; /*邻接矩阵*/
int vexNum, edgNum; /*图中顶点数和边数*/
}mgraphtype;
3.3 基本算法实现
int menu(); /*主菜单*/
void Create_Map(mgraphtype *g); /*从文件读取信息建立图*/
void Print_Map(); /*显示校园景点地图*/
int Judge_Input(int num); /*判断输入的编号是否合理*/
void Search_Location(mgraphtype *g); /*景点信息查询*/
void ShortPath(mgraphtype *g); /*求景点间最短路径*/
void Floyd_Print(mgraphtype *g, int sNum, int eNum);/*递归打印两点间最短路径*/
void Shortpath_Print(mgraphtype *g); /*输出并打印两点间的最短路径*/
void Dfs_Print(mgraphtype *g, int sNum, int eNum);/*深度优先遍历查询两景点间所有路径*/
void Allpath_Print(mgraphtype *g); /*查询两顶点间的所有路径并打印*/
void BestPath(mgraphtype *g); /*多顶点间求最佳路径*/
void System_Exit(int *q); /*退出系统*/
3.4 系统开发平台要求
- 基于 Visual Studio 2017的C语言进行系统开发。
3.5 参考书籍
- [1] 李云清,杨庆红.数据结构(C语言版).北京:人民邮电出版社,2014.
- [2] 严蔚敏,吴伟民.数据结构(C语言版).北京:清华大学出版.1997.
- [3] 周海英,马巧梅,靳雁霞.数据结构与算法设计.北京:国防工业出版社,2009.
五、项目附加功能
- 1. 登录系统,保障校园导游咨询系统的安全运行。
- 2. 公告栏,使游客及时了解学校动态,便于游客的游览。
- 3. 管理员系统,及时发布公告信息和对景点的有效管理。
六、核心功能代码实现
1. 景点信息查询
void Search_Location(mgraphtype *g) {
int s;
do {
printf("\n请输入你要查找的景点编号:");
scanf("%d", &s);
} while (Judge_Input(s));
printf("\n景点名称:[%s]\n\n", g->vexs[s - 1].name);
printf("景点简介: %s\n\n", g->vexs[s - 1].intro);
}
2. Floyd算法求两景点间的一条最短的路径
int dist[M][M]; /*距离向量*/
int path[M][M]; /*路径向量*/
void ShortPath(mgraphtype *g) {
int i, j, k;
for (i = 0; i < g->vexNum; i++) /*初始化距离向量矩阵与路径向量矩阵*/
for (j = 0; j < g->vexNum; j++) {
dist[i][j] = g->edge[i][j];
if (i != j && dist[i][j] < INFINITY) path[i][j] = i;
else path[i][j] = -1; /*-1代表当前两点不可达*/
}
for (k = 0; k < g->vexNum; k++) /*递推求解每两景点的最短路径*/
for (i = 0; i < g->vexNum; i++)
for (j = 0; j < g->vexNum; j++) /*更新dist[i][j]的值*/
if (dist[i][j] >(dist[i][k] + dist[k][j])) {
dist[i][j] = dist[i][k] + dist[k][j];
path[i][j] = k; /*path用于记录最短路径上的经结点*/
}
}
3. 递归实现打印两点间的最短路径
void Floyd_Print(mgraphtype *g, int sNum, int eNum) {
if (path[sNum][eNum] == -1 || path[sNum][eNum] == eNum || path[sNum][eNum] == sNum)
return;
else {
Floyd_Print(g, sNum, path[sNum][eNum]); /*将中间点作为终点继续打印路径*/
printf("%s->", g->vexs[path[sNum][eNum]].name); /*打印中间景点名字*/
Floyd_Print(g, path[sNum][eNum], eNum); /*将中间点作为起点继续打印路径*/
}
}
4. 深度优先遍历查询任意两个景点之间的所有路径
int pathStack[M]; /*路径栈,存储路径信息*/
int top; /*栈顶*/
int visited[M]; /*入栈标记,防止形成回路*/
int count; /*路径计数器*/
void Dfs_Print(mgraphtype *g, int sNum, int eNum) {
int dis = 0; /*用于记录路径长度*/
pathStack[top] = sNum; /*将本趟起点入栈*/
top++;
visited[sNum] = 1; /*将入栈点标记为已入栈*/
for (int i = 0; i < g->vexNum; i++) {
if (g->edge[sNum][i] > 0 && g->edge[sNum][i] != INFINITY && !visited[i]) {
/*表明前一个入栈点与该点可达,且该点未入栈(未被访问)*/
if (i == eNum) { /*如果深度遍历搜到了终点,就输出刚才的路径*/
printf("第%d条路:", count++);
for (int j = 0; j < top; j++) {
printf("%s->", g->vexs[pathStack[j]].name);
if (j < top - 1)
dis = dis + g->edge[pathStack[j]][pathStack[j + 1]]; /*统计路径长度*/
}
dis = dis + g->edge[pathStack[top - 1]][eNum]; /*最后一条路单独出来,因为enum不能入栈*/
printf("%s\n", g->vexs[eNum].name);
printf("总长度是:%dm\n\n", dis);
}
else {
Dfs_Print(g, i, eNum); /*如果该点不是终点,接着深度搜索*/
top--; /*支路全被访问一遍后,顶点出栈*/
visited[i] = 0; /*将出栈点标记为已出栈,允许下次访问*/
}
}
}
}
5. 查询任意两个景点之间的所有路径并打印
void Allpath_Print(mgraphtype *g) {
int sNum, eNum;
count = 1; /*路径计数器*/
top = 0; /*栈顶*/
memset(pathStack, 0, sizeof(pathStack)); /*路径栈初始化*/
memset(visited, 0, sizeof(visited)); /*入栈标记初始化*/
do {
printf("\n请输入起点编号:");
scanf("%d", &sNum);
} while (Judge_Input(sNum));
do {
printf("\n请输入终点编号:");
scanf("%d", &eNum);
} while (Judge_Input(eNum));
printf("\n");
Dfs_Print(g, sNum - 1, eNum - 1);
}
6. 多景点间求最佳路径
void BestPath(mgraphtype *g) {
int vNum[M] = { 0 }, j = 1; /*记录用户输入的编号信息*/
int d = 0; /*统计全程总长*/
printf("\n请输入你要游览的第%d个景点的编号(输入-1结束输入):", j);
scanf("%d", &vNum[j - 1]);
while (vNum[j - 1] != -1 && j < 12) {
while (Judge_Input(vNum[j - 1])) {
printf("\n请输入你要游览的第%d个景点编号:", j);
scanf("%d", &vNum[j - 1]);
}
if (vNum[j - 1] == -1) break;
printf("\n请输入你要游览的第%d个景点编号:", ++j);
scanf("%d", &vNum[j - 1]);
}
printf("\n这是最佳访问路径:");
for (int i = 0; vNum[i] > 0 && vNum[i + 1] > 0; i++) {
printf("%s->", g->vexs[vNum[i] - 1].name); /*输出路径上的起点*/
Floyd_Print(g, vNum[i] - 1, vNum[i + 1] - 1); /*利用Floyd算法*/
d += dist[vNum[i] - 1][vNum[i + 1] - 1];
}
printf("%s\n\n", g->vexs[vNum[j - 2] - 1].name); /*输出路径上的终点*/
printf("全程总长为:%dm\n\n", d);
}
完整代码请移步本人GitHub:校园导游咨询系统