武汉科技大学2023数据结构课程设计
旅游区景点导游系统
针对游客的不同需求,设计一款旅游区景点导游系统。
基本功能及要求如下:
- 提供用户操作的菜单和界面,实现系统的所有功能。
- 旅游区所有景点信息,要求以文件的形式存储(如文本文件),格式自行设计。
- 提供对旅游区所有景点信息的查询、编辑功能,可进行查找、添加、删除和修改等操作,修改后的信息需要保存回文件。
- 提供旅游区当前景点显示功能,要求能显示游客当前所在景点及所有与游客所在景点相邻景点信息。
- 提供查询从旅游区每个景点出发到其他任一景点的最短简单路径及距离的功能。
- 提供查询旅游区任意两个景点之间所有简单路径及距离、最短简单路径及距离的功能。
- 提供最佳游览路线推荐功能,即确定从某一景点出发,经过景区所有景点(景点可以重复)且距离最短的游览路线。
代码展示
1.sy.h
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_PEAK 120 //最多景点数量
#define INF 999999
typedef struct // 景点信息结构体
{
int number; //景点编号
char name[20]; // 景点名称
char introduce[200]; // 景点介绍
} Attraction;
struct Graph // 图结构体
{
Attraction attractions[MAX_PEAK]; // 景点数组
int adjacency_matrix[MAX_PEAK][MAX_PEAK]; // 邻接矩阵
int num_attractions; // 景点数
int num_paths; // 路线数
};
extern struct Graph graph; //定义全局变量图表
void menu();
void load_graph();// 读取文件,创建图表信息
void save_graph();// 保存图表信息到文件
void getAttractionInfo(); // 查询景点信息
void addAttractionInfo(); // 添加景点信息
void removeAttractionInfo(); // 删除景点信息
void modifyAttractionInfo(); // 修改景点信息
void addRouteInfo(); //添加路线
void display_current_attraction();// 显示当前景点及相邻景点
void get_shortest_route_from_current_attraction();// 查询从当前景点到其他景点的最短路径和距离
void get_all_routes_and_distances();// 查询任意两个景点之间所有路径和距离
2.attraction_man.cpp
#include "sy.h"
void getAttractionInfo()// 查询景点信息
{
int i, number;
printf("请输入要查询的景点ID:");
scanf("%d", &number);
for (i = 0; i < MAX_PEAK; i++)
{
if (graph.attractions[i].number == number)
{
printf("景点编号:%d\n", graph.attractions[i].number);
printf("景点名称:%s\n", graph.attractions[i].name);
printf("景点介绍:%s\n", graph.attractions[i].introduce);
return;
}
}
printf("没有找到该景点!\n");
}
void addAttractionInfo()// 添加景点
{
int i;
graph.attractions[graph.num_attractions].number = graph.num_attractions;
printf("请输入景点名称:");
scanf("%s", graph.attractions[graph.num_attractions].name);
printf("请输入景点介绍:");
scanf("%s", graph.attractions[graph.num_attractions].introduce);
graph.num_attractions++;
printf("添加景点信息成功!\n");
}
void removeAttractionInfo()// 删除景点
{
int i,j;
int id;
printf("请输入要删除的景点ID:");
scanf("%d", &id);
int flag = 0;
// 删除与该景点有关的所有路线
for (i = 0; i < MAX_PEAK; i++) {
if (graph.adjacency_matrix[id][i] != 0) {
graph.adjacency_matrix[id][i] = 0;
graph.adjacency_matrix[i][id] = 0;
graph.num_paths--;
}
}
// 删除该景点
for (i = 0; i < MAX_PEAK; i++) {
if (graph.attractions[i].number == id) {
flag = 1;
for (j = i; j < graph.num_attractions - 1; j++)
{
graph.attractions[j] = graph.attractions[j + 1];
}
graph.num_attractions--;
break;
}
}
if (flag == 0)printf("没有找到该景点!\n");
else printf("删除成功!\n");
}
void modifyAttractionInfo()// 修改景点信息
{
int i, id;
printf("请输入要修改的景点ID:");
scanf("%d", &id);
for (i = 0; i < MAX_PEAK; i++)
{
if (graph.attractions[i].number == id)
{
printf("请输入景点名称:");
scanf("%s", graph.attractions[i].name);
printf("请输入景点介绍:");
scanf("%s", graph.attractions[i].introduce);
printf("修改景点信息成功!\n");
return;
}
}
printf("没有找到该景点信息!\n");
}
void addRouteInfo()//添加路线
{
int src, des, dis;
printf("请输入路线起点、终点和距离:");
scanf("%d%d%d", &src, &des, &dis);
int flag = 0;
for (int i = 0; i < MAX_PEAK; i++)
{
if (graph.attractions[i].number == src)flag++;
if (graph.attractions[i].number == des)flag++;
}
if (flag == 0 || flag == 1)
{
printf("没有此景点!\n");
return;
}
graph.adjacency_matrix[src][des] = dis;
graph.adjacency_matrix[des][src] = dis;
graph.num_paths++;
printf("添加成功!\n");
}
3.file_read_load.cpp
#include "sy.h"
// 读取景点信息文件
void load_graph()
{
FILE* fp;
int i, j;
char name[20], introduce[200];
memset(graph.adjacency_matrix, 0, sizeof(graph.adjacency_matrix)); // 初始化邻接矩阵
fp = fopen("graph.txt", "r");
if (fp == NULL)
{
printf("打开文件失败\n");
return;
}
fscanf(fp, "%d %d", &graph.num_attractions, &graph.num_paths);
for (i = 0; i < graph.num_attractions; i++) // 读取每个景点的信息
{
fscanf(fp, "%d %s %s\n", &graph.attractions[i].number, graph.attractions[i].name, graph.attractions[i].introduce);
}
int spot1, spot2, weight;
for (i = 0; i < graph.num_paths; i++) // 读取每条边的信息
{
fscanf(fp, "%d %d %d", &spot1, &spot2, &weight);
graph.adjacency_matrix[spot1][spot2] = weight;
graph.adjacency_matrix[spot2][spot1] = weight;
}
fclose(fp);
}
// 保存景点信息到文件
void save_graph()
{
FILE* fp;
int i, j;
fp = fopen("graph.txt", "w");
if (fp == NULL)
{
printf("打开文件失败\n");
return;
}
fprintf(fp, "%d %d\n", graph.num_attractions, graph.num_paths); // 写入景点数和边数
for (i = 0; i < graph.num_attractions; i++) // 写入每个景点的信息
{
fprintf(fp, "%d %s %s\n", graph.attractions[i].number, graph.attractions[i].name, graph.attractions[i].introduce);
}
for (i = 0; i < graph.num_paths; i++) // 写入邻接矩阵
{
for (j = 0; j < graph.num_paths; j++)
{
if (graph.adjacency_matrix[i][j] != 0 && i < j)
{
fprintf(fp, "%d %d %d\n", i, j, graph.adjacency_matrix[i][j]);
}
}
}
fclose(fp);
}
4.menu.cpp
#include "sy.h"
void menu()
{
int as;
while (1)
{
printf("==== 旅游区景点导游系统 ====\n");
printf("1. 查询景点信息\n");
printf("2. 添加景点信息\n");
printf("3. 删除景点信息\n");
printf("4. 修改景点信息\n");
printf("5. 添加路线信息\n");
printf("6. 当前景点显示\n");
printf("7. 查询当前景点最短路线 \n");
printf("8. 查询所有路径和距离\n");
printf("9. 退出系统 \n");
printf("请输入您的选择:");
scanf("%d", &as);
switch (as)
{
case 1:
getAttractionInfo();
break;
case 2:
addAttractionInfo();
break;
case 3:
removeAttractionInfo();
break;
case 4:
modifyAttractionInfo();
break;
case 5:
addRouteInfo();
break;
case 6:
display_current_attraction();
break;
case 7:
get_shortest_route_from_current_attraction();
break;
case 8:
get_all_routes_and_distances();
break;
case 9:
save_graph();
exit(0);
break;
default:
printf("没有此选项,请重新选择!\n");
break;
}
}
}
5.mgragh.cpp
#include "sy.h"
struct Graph graph;
// 主函数
int main()
{
load_graph();
menu();
return 0;
}
void display_current_attraction() {
int spot_id;
printf("请输入当前景点ID:");
scanf("%d", &spot_id);
int flag = -1;
for (int i = 0; i < MAX_PEAK; i++)
{
if (graph.attractions[i].number == spot_id)
{
flag = i;
printf("您当前所在景点信息:\n");
printf("景点编号:%d\n", graph.attractions[i].number);
printf("景点名称:%s\n", graph.attractions[i].name);
printf("景点介绍:%s\n", graph.attractions[i].introduce);
break;
}
}
if (flag == -1) {
printf("景点信息不存在!\n");
return;
}
printf("您的相邻景点信息:\n");
for (int i = 0; i < MAX_PEAK; i++) {
if (graph.adjacency_matrix[flag][i] !=0) {
printf("景点编号:%d\n", graph.attractions[i].number);
printf("景点名称:%s\n", graph.attractions[i].name);
printf("景点介绍:%s\n", graph.attractions[i].introduce);
}
}
}
int dist[MAX_PEAK];
int prev[MAX_PEAK];
int visited[MAX_PEAK];
int path[MAX_PEAK];
void dijkstra(int start)
{
// 初始化距离数组、前驱数组和 visited 数组
for (int i = 0; i < MAX_PEAK; i++) {
dist[i] = INF;
prev[i] = -1;
visited[i] = 0;
}
dist[start] = 0;
// Dijkstra 算法
for (int i = 0; i < MAX_PEAK; i++)
{
int min_dist = INF, min_index = -1;
for (int j = 0; j < MAX_PEAK; j++) // 选择当前距离最小的顶点
{
if (!visited[j] && dist[j] < min_dist)
{
min_dist = dist[j];
min_index = j;
}
}
if (min_index == -1) // 如果没有找到未访问过的顶点,则算法结束
{
break;
}
visited[min_index] = 1;// 标记该顶点为已访问
// 更新与该顶点相邻的顶点的距离和前驱
for (int j = 0; j < MAX_PEAK; j++)
{
if (graph.adjacency_matrix[min_index][j] != 0)
{
int new_dist = dist[min_index] + graph.adjacency_matrix[min_index][j];
if (new_dist < dist[j]) {
dist[j] = new_dist;
prev[j] = min_index;
}
}
}
}
}
void get_shortest_route_from_current_attraction()
{
int start;
printf("请输入当前景点ID:");
scanf("%d", &start);
int flag = 0;
for (int i = 0; i < MAX_PEAK; i++)
{
if (graph.attractions[i].number == start)
flag = 1;
}
if (flag == 0)
{
printf("景点不存在!\n");
return;
}
dijkstra(start); // 计算最短路径
printf("该景点路线如下:\n");
for (int i = 0; i < MAX_PEAK; i++) {
if (dist[i] == 999999) continue;
if (i != start)
{
int path[MAX_PEAK], path_length = 0;
int cur = i;
while (cur != -1) {
path[path_length++] = cur;
cur = prev[cur];
}
for (int j = path_length - 1; j >= 0; j--) {
printf("%s", graph.attractions[path[j]].name);
if (j > 0) {
printf(" -> ");
}
}
printf(" 总距离:%dm", dist[i]);
printf("\n");
}
}
}
void print_all_paths(int start, int end, int len, int distance) {
visited[start] = 1;
path[len] = start;
len++;
if (start == end) {
printf("路线如下:");
for (int i = 0; i < len; i++) {
printf("%s ", graph.attractions[path[i]].name);
if (i != len - 1) {
printf("-> ");
}
}
printf(" 距离:%dm\n", distance);
}
else {
for (int i = 0; i < MAX_PEAK; i++) {
if (graph.adjacency_matrix[start][i] != 0 && !visited[i]) {
int new_distance = distance + graph.adjacency_matrix[start][i];
print_all_paths(i, end, len, new_distance);
}
}
}
visited[start] = 0;
len--;
}
void get_all_routes_and_distances()
{
int start, end;
int distance = 0;
printf("请输入起点编号:");
scanf("%d", &start);
printf("请输入终点编号:");
scanf("%d", &end);
int flag = 0;
for (int i = 0; i < MAX_PEAK; i++)
{
if (graph.attractions[i].number == start)flag ++;
if (graph.attractions[i].number == end)flag++;
}
if (flag == 0||flag==1)
{
printf("您查询的景点不存在!\n");
return;
}
memset(visited, 0, sizeof(visited));
memset(dist, 0, sizeof(dist));
visited[start] = 1;
path[0] = start;
printf("两景点路线如下:\n");
print_all_paths(start, end, 0,distance);
dijkstra(start);
int len = 0;
int p = end;
while (p != -1) {
path[len++] = p;
p = prev[p];
}
printf("最短路线为:",graph.attractions[end].name);
for (int i = len - 1; i >= 0; i--) {
printf("%s", graph.attractions[path[i]].name);
if (i > 0) {
printf(" -> ");
}
}
printf(" 总距离:%dm\n",dist[end]);
}