概述
文章目录
- 一、实验任务
- 1.1、实验要求
- 1.2、景点数据
- 二、效果展示
- 2.1、欢迎界面
- 2.2、创建景点景区图
- 2.3、查询景点信息
- 2.4、旅游景点导航
- 2.5、搜索最短路径
- 2.6、铺设电路规划
- 三、源码
- 3.1、Graph.cpp
- 3.2、Graph.h
- 3.3、main.cpp
- 3.4、Tourism.cpp
- 3.5、Tourism.h
一、实验任务
1.1、实验要求
现有一个景区,景区里面有若干个景点,景点之间满足以下条件:
- 某些景点之间铺设了道路(相邻)
- 这些道路都是可以双向行驶的(无向图)
- 从任意一个景点出发都可以游览整个景区(连通图)
开发景区信息管理系统,对景区的信息进行管理。使用图的数据结构来保存景区景点 信息,为用户提供创建图、查询景点信息、旅游景点导航、搜索最短路径、铺设电路规划等功能
1.2、景点数据
景区的数据包含景点信息和景点之间的道路信息,分别由两个文本文件存储
Vex.txt
文件用来存储景点信息
7
0
A区
风景优美,气候宜人。门票10元。
1
B区
风景优美,气候宜人。门票20元。
2
C区
风景优美,气候宜人。门票30元。
3
D区
风景优美,气候宜人。门票40元。
4
E区
风景优美,气候宜人。门票50元。
5
F区
风景优美,气候宜人。门票60元。
6
G区
风景优美,气候宜人。门票70元。
Edge.txt
文件用来存储道路信息
0 2 700
0 4 1000
0 5 600
1 2 1000
1 6 1000
2 3 400
3 4 300
3 6 400
4 5 600
5 6 500
二、效果展示
2.1、欢迎界面
2.2、创建景点景区图
2.3、查询景点信息
2.4、旅游景点导航
2.5、搜索最短路径
2.6、铺设电路规划
三、源码
3.1、Graph.cpp
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include"Graph.h"
extern Graph m_Graph;
//函数名:Init
//参数:void
//返回值:void
//功能:实现图的初始化,权值信息都初始化为0
void Init(void)
{
for (int i = 0; i < 20; i++) {
for (int j = 0; j < 20; j++) {
m_Graph.m_aAdjMatrix[i][j] = 0; //权值信息初始化为0
}
m_Graph.m_nVexNum = 0; //景点数目初始化为0
}
}
//函数名:InsertVex
//参数:结构体vex
//返回值:true:顶点未满 false:顶点已满
//功能:通过传入结构体,将顶点的相关信息插入到顶点信息数组中
bool InsertVex(Vex sVex)
{
if (m_Graph.m_nVexNum == 20) {
//顶点已满
return false;
}
m_Graph.m_aVexs[m_Graph.m_nVexNum++] = sVex; //插入顶点信息
return true;
}
//函数名:InsertEdge
//参数:Edge结构体
//返回值:true:插入成功 false:下表越界
//功能:通过传入Edge结构体,将边的相关信息插入到权值矩阵中
bool InsertEdge(Edge sEdge)
{
if (sEdge.vex1 < 0 || sEdge.vex1 >= m_Graph.m_nVexNum || sEdge.vex2 < 0 || sEdge.vex2 >= m_Graph.m_nVexNum) {
//下标越界
return false;
}
//插入边的信息
m_Graph.m_aAdjMatrix[sEdge.vex1][sEdge.vex2] = sEdge.weight;
m_Graph.m_aAdjMatrix[sEdge.vex2][sEdge.vex1] = sEdge.weight;
return true;
}
//函数名:GetVex
//参数:输入的编号
//返回值:对应编号的顶点信息结构体
//功能:通过传入的顶点编号,返回对应顶点信息结构体
Vex GetVex(int v)
{
return m_Graph.m_aVexs[v];
}
//函数名:FindEdge
//参数:nVex:想要查询的顶点 aEdge[]:
//返回值:边的条数
//功能:查询与指定顶点相连的边
int FindEdge(int nVex, Edge aEdge[])
{
int k = 0;
//遍历整个图的邻接矩阵
for (int i = 0; i < 20; i++) {
if (m_Graph.m_aAdjMatrix[nVex][i] != 0 && nVex != i) {
//得到边的信息
aEdge[k].vex1 = nVex;
aEdge[k].vex2 = i;
aEdge[k].weight = m_Graph.m_aAdjMatrix[nVex][i];
k++;
}
}
return k;
}
//函数名:DFS
//参数:int nVex:顶点编号 bVisted[]:bool类型的数组,用来记录某个顶点是否被遍历过 int &nIndex:记录遍历深度 PathList &pList:遍历得到的结果
//返回值:void
//功能:使用深度优先搜索算法遍历图
void DFS(int nVex, bool isVisited[], int& nIndex, PathList& pList)
{
isVisited[nVex] = true; //修改为已访问
pList->vexs[nIndex++] = nVex; //访问顶点nVex
int num = 0; //被访问过的节点数
for (int i = 0; i < m_Graph.m_nVexNum; i++) {
if (isVisited[i]) {//如果当前i节点被访问过,则num++
num++;
}
}
if (num == m_Graph.m_nVexNum) {//如果所有节点都被访问过
//保存一条路径
pList->next = new Path;
for (int i = 0; i < m_Graph.m_nVexNum; i++) {
pList->next->vexs[i] = pList->vexs[i];
}
pList = pList->next;
pList->next = NULL;
}
else {
for (int w = 0; w < m_Graph.m_nVexNum; w++) {//搜索v的所有邻接点
if (m_Graph.m_aAdjMatrix[nVex][w] > 0 && !isVisited[w]) { //如果w是nVex的邻接点并未被访问
DFS(w, isVisited, nIndex, pList); //递归调用DFS
isVisited[w] = false; //改为未访问
nIndex--; //索引值减1
}
}
}
}
//函数名:DFSTraverse
//参数:int nVex:顶点编号 PathList &pList:遍历得到的结果
//返回值:void
//功能:通过调用DFS()函数,得到深度有限搜索遍历的结果
void DFSTraverse(int nVex, PathList& pList)
{
int nIndex = 0;
bool bVisited[20] = { false };
DFS(nVex, bVisited, nIndex, pList);
}
//函数名:FindShortPath
//功能:寻找最短路径
//参数:景点的起始跟目的编号;边的路径结构数组
//返回值:nIndex
int FindShortPath(int nVexStart, int nVexEnd, Edge aPath[])
{
int nShortPath[20][20]; //最短路径,行表示终点,列表示从起点到终点的最短路径的每一步
int nShortDistance[20]; //保存从起点到任一顶点的最短距离
bool aVisited[20]; //判断某点是否已在最短路径中
int v; //每一次找到的可以加入集合的顶点
//初始化
for (v = 0; v < m_Graph.m_nVexNum; v++) {
aVisited[v] = false;
if (m_Graph.m_aAdjMatrix[nVexStart][v] != 0) {
//如果顶点v和nVexStart相连,则最短距离设置为两顶点间的距离
nShortDistance[v] = m_Graph.m_aAdjMatrix[nVexStart][v];
}
else {
//如果不相连,则最短距离设置为最大值
nShortDistance[v] = 0x7FFFFFFF;
}
nShortPath[v][0] = nVexStart; //起始点为nVexStart
//初始化最短路径
for (int w = 1; w < m_Graph.m_nVexNum; w++) {
nShortPath[v][w] = -1;
}
}
//初始化,将nVexStart顶点加入到集合中
aVisited[nVexStart] = true;
int min; //暂存路径的最小值
for (int i = 1; i < m_Graph.m_nVexNum; i++) {
min = 0x7FFFFFFF;
bool bAdd = false; //判断是否还有顶点可以加入集合
for (int w = 0; w < m_Graph.m_nVexNum; w++) {
if (!aVisited[w] && nShortDistance[w] < min) {
v = w; //w顶点距离nVexStart顶点最近
min = nShortDistance[w]; //w到nVexStart的最短距离为min
bAdd = true;
}
}
//如果没有顶点可以加入到集合,则跳出循环
if (!bAdd) {
break;
}
aVisited[v] = true; //将w顶点加入到集合
nShortPath[v][i] = v; //每次找到最短路径后,就相当于从源点出发到了终点,所以nShortPath[v][i]=v
for (int w = 0; w < m_Graph.m_nVexNum; w++) {
//将w作为中间点计算nVexStart到所有顶点的最短距离
if (!aVisited[w] && (min + m_Graph.m_aAdjMatrix[v][w] < nShortDistance[w]) && (m_Graph.m_aAdjMatrix[v][w] > 0)) {
//如果有新的最短距离,则更新最短路径及距离
nShortDistance[w] = min + m_Graph.m_aAdjMatrix[v][w];
for (int i = 0; i < m_Graph.m_nVexNum; i++) {
//如果通过w到达顶点i的距离比较短,则将w的最短路径赋值给i
nShortPath[w][i] = nShortPath[v][i];
}
}
}
}
int nIndex = 0;
int nVex1 = nVexStart;
//将最短路径保存到边的结构体数组中
for (int i = 1; i < m_Graph.m_nVexNum; i++) {
if (nShortPath[nVexEnd][i] != -1) {
aPath[nIndex].vex1 = nVex1;
aPath[nIndex].vex2 = nShortPath[nVexEnd][i];
aPath[nIndex].weight = m_Graph.m_aAdjMatrix[nVex1][aPath[nIndex].vex2];
nVex1 = nShortPath[nVexEnd][i];
nIndex++;
}
}
return nIndex;
}
//函数名:FindMinTree
//功能:通过Prim算法构建最小生成树
//参数:Edge aPath[]
//返回值:void
void FindMinTree(Edge aPath[])
{
bool aVisited[20] = { false }; //判断某顶点是否在最小生成树中
aVisited[0] = true; //从0号顶点开始,加入到集合中
int min;
int nVex1, nVex2;
for (int k = 0; k < m_Graph.m_nVexNum - 1; k++) {
min = 0X7FFFFFFF;
for (int i = 0; i < m_Graph.m_nVexNum; i++) {
//从集合中取一个顶点
if (aVisited[i]) {
for (int j = 0; j < m_Graph.m_nVexNum; j++) {
//从不在集合的顶点中取出一个顶点
if (!aVisited[j]) {
if ((m_Graph.m_aAdjMatrix[i][j] < min) && (m_Graph.m_aAdjMatrix[i][j] != 0)) {
nVex1 = i;
nVex2 = j;
//找出最短边
min = m_Graph.m_aAdjMatrix[i][j];
}
}
}
}
}
//保存最短边的两个顶点
aPath[k].vex1 = nVex1;
aPath[k].vex2 = nVex2;
aPath[k].weight = m_Graph.m_aAdjMatrix[nVex1][nVex2];
//将两个顶点加入集合
aVisited[nVex1] = true;
aVisited[nVex2] = true;
}
}
3.2、Graph.h
#pragma once
//存储图的顶点信息
struct Vex
{
int num; //景点编号
char name[20]; //景点名字
char desc[1024]; //景点介绍
};
//存储边的信息
struct Edge
{
int vex1; //边的第一个顶点
int vex2; //边的第二个顶点
int weight; //权值
};
//顶点数组和邻接矩阵,用来保存图的信息
struct Graph
{
int m_aAdjMatrix[20][20]; //邻接矩阵
Vex m_aVexs[20]; //顶点信息数组
int m_nVexNum; //当前图的顶点个数
};
//定义链表PathList来保存所有路径
typedef struct Path
{
int vexs[20]; //保存一条路径
Path* next; //下一条路径
}*PathList;
//初始化图
void Init(void);
//插入顶点信息
bool InsertVex(Vex sVex);
//插入边的信息
bool InsertEdge(Edge sEdge);
//通过传入的顶点编号,返回对应顶点信息结构体
Vex GetVex(int v);
//查询所有与指定顶点相连的边
int FindEdge(int v, Edge aEdge[]);
//使用深度优先搜索算法遍历图
void DFS(int nVex, bool isVisited[], int& nIndex, PathList& pList);
//通过调用DFS()函数,得到深度有限搜索遍历的结果
void DFSTraverse(int nVex, PathList& pList);
//寻找最短路径
int FindShortPath(int nVexStart, int nVexEnd, Edge aPath[]);
//通过Prim算法构建最小生成树
void FindMinTree(Edge aPath[]);
3.3、main.cpp
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include"Tourism.h"
#include"Graph.h"
using namespace std;
Graph m_Graph;
int main(void)
{
int choice;
//系统界面
printf("nnnnnnnnnnnnnntttttt");
printf("*欢迎进入景区管理系统*");
printf("nnnnnnnnnnnnntttttt");
system("pause");
system("cls");
do {
//输出系统菜单
cout << "=====景区信息管理系统=====" << endl;
cout << "* 1.创建景区景点图 *" << endl;
cout << "* 2.查询景点信息 *" << endl;
cout << "* 3.旅游景点导航 *" << endl;
cout << "* 4.搜索最短路径 *" << endl;
cout << "* 5.铺设电路规划 *" << endl;
cout << "* 0.退出 *" << endl;
cout << "==========================" << endl;
//用户选择功能
cout << "请输入菜单项编号(0-5):";
cin >> choice;
cout << endl;
switch (choice)
{
case 1:CreateGraph(); break;
case 2:GetSpotInfo(); break;
case 3:TravelPath(); break;
case 4:FindShortPath(); break;
case 5:DesignPath(); break;
case 0:cout << "谢谢您使用本系统!" << endl; break;
default:cout << "您的输入有误!请重新输入!" << endl << endl;;
}
} while (choice != 0);
return 0;
}
3.4、Tourism.cpp
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<fstream>
#include <string.h>
#include<stdlib.h>
#include"Graph.h"
using namespace std;
extern Graph m_Graph;
//函数名:LoadVex
//参数:void
//返回值:void
//功能:实现从Vex.txt文件中读取景点信息并输出
void LoadVex(void)
{
ifstream VexFile("Vex.txt");
if (!VexFile) {
cout << "Vex.txt文件打开失败,请检查!" << endl;
return;
}
//暂存从Vex.txt读取到的一行数据
char num[2];
char name[20];
char desc[1024];
Vex sVex;
//逐行读取Vex.txt中的数据
VexFile.getline(num, 2); //将第一行的数据读出丢掉
cout << "景区数目:" << atoi(num) << endl;
cout << "-----顶点-----" << endl;
//将顶点信息保存到顶点数组中
while (VexFile.getline(num, 2)) {
sVex.num = atoi(num);
VexFile.getline(name, 20);
strcpy(sVex.name, name);
VexFile.getline(desc, 1024);
strcpy(sVex.desc, desc);
//将顶点信息输出
cout << sVex.num << "-" << sVex.name << endl;
//设置图的顶点
if (!InsertVex(sVex)) {
cout << "新增景点失败!" << endl;
continue;
}
}
cout << "------------" << endl;
VexFile.close();
}
//函数名:LoadPath
//参数:void
//返回值:void
//功能:实现从Edge.txt文件中读取路径信息并输出
void LoadPath()
{
ifstream EdgeFile("Edge.txt");
if (!EdgeFile) {
cout << "Edge.txt文件打开失败,请检查!" << endl;
return;
}
Edge edge;
cout << "------边------" << endl;
while (EdgeFile) {
EdgeFile >> edge.vex1 >> edge.vex2 >> edge.weight;
cout << "<" << edge.vex1 << "," << edge.vex2 << "> " << edge.weight << endl;
//设置图的边
if (!InsertEdge(edge)) {
cout << "新增路径信息失败!" << endl;
continue;
}
}
cout << "-------------" << endl;
EdgeFile.close();
cout << "======================" << endl;
}
//函数名:CreateGraph
//参数:void
//返回值:void
//功能:读取文件,获取景点信息和道路信息
void CreateGraph(void)
{
cout << "n=====创建景点景区图=====" << endl;
Init();//初始化图
LoadVex();//从Vex.txt文件中读取景点信息并输出
LoadPath();//从Edge.txt文件中读取路径信息并输出
cout << endl;
}
//函数名:GetSpotInfo
//参数:void
//返回值:void
//功能:调用GetVex()函数,得到所有顶点信息并输出
void GetSpotInfo(void)
{
cout << "n=====查询景点信息=====" << endl;
int nVexNum = m_Graph.m_nVexNum;
if (nVexNum == 0) {
cout << "请先创建图!" << endl;
return;
}
//将景点信息罗列出来,供用户查询选择
for (int i = 0; i < m_Graph.m_nVexNum; i++) {
Vex sVex = GetVex(i);
cout << i << "-" << sVex.name << endl;
}
cout << "====================" << endl;
//提示用户根据编号进行查询
cout << "n请输入想要查询的景点编号:";
int num;
cin >> num;
if (num < 0 || num >= m_Graph.m_nVexNum) {
cout << "您的输入有误!请重新输入!" << endl;
cout << "n请输入想要查询的景点编号:";
cin >> num;
}
else {
Vex sVex = GetVex(num);
cout << "----------------------------" << endl;
cout << sVex.name << ":" << sVex.desc << endl;
cout << "----------------------------" << endl;
cout << "-----周边景区-----" << endl;
Edge aEdge[20];
int EdgeNum = FindEdge(num, aEdge);
for (int i = 0; i < EdgeNum; i++) {
Vex v1 = GetVex(aEdge[i].vex1);
Vex v2 = GetVex(aEdge[i].vex2);
cout << v1.name << "->" << v2.name << " " << aEdge[i].weight << "m" << endl;
}
cout << "------------------" << endl;
}
cout << endl;
}
//函数名:TravelPath
//参数:void
//返回值:void
//功能:通过调用DFSTraverse()函数,实现旅游景点导航功能,将查询到的景点导航路线显示在界面上
void TravelPath()
{
cout << "n=======旅游景点导航======" << endl;
int nVexNum = m_Graph.m_nVexNum;
if (nVexNum == 0) {
cout << "请先创建图!" << endl;
return;
}
for (int i = 0; i < m_Graph.m_nVexNum; i++) {
Vex sVex = GetVex(i);
cout << "*t" << i << "-" << sVex.name << "tt*" << endl;
}
cout << "=========================" << endl;
//输入景点编号
cout << "请输入想要导航的起始点编号:";
int startNum;
cin >> startNum;
if (startNum < 0 || startNum >= m_Graph.m_nVexNum) {
cout << "您输入的编号有误!" << endl;
return;
}
//遍历景区景点图
PathList pList = new Path;
PathList pHead = pList;
DFSTraverse(startNum, pList);
cout << endl;
//输出遍历结果
cout << "导航路线为:" << endl;
int i = 1;
pList = pHead;
while (pList->next != NULL) {
Vex vex = GetVex(pList->vexs[0]);
cout << "路线" << i++ << ":" << vex.name;
for (int j = 1; j < m_Graph.m_nVexNum; j++) {
vex = GetVex(pList->vexs[j]);
cout << "->" << vex.name;
}
cout << endl;
pList = pList->next;
}
cout << endl;
delete pList;
pList = NULL;
pHead = NULL;
}
//函数名:FindShortPath
//功能:调用Graph.cpp文件中的FindShortPath函数查询两个景点间的最短路径和距离
//参数:void
//返回值:void
void FindShortPath(void)
{
cout << "n======搜索最短路径======n";
int nVexNum = m_Graph.m_nVexNum;
if (nVexNum == 0) {
cout << "请先创建图!" << endl;
return;
}
for (int i = 0; i < m_Graph.m_nVexNum; i++) {
Vex sVex = GetVex(i);
cout << "*t" << i << "-" << sVex.name << "tt*" << endl;
}
cout << "========================n";
//输入两个景点的编号
int start_place, end_place;
cout << "请输入起点的编号:";
cin >> start_place;
cout << "请输入终点的编号:";
cin >> end_place;
if (start_place < 0 || start_place >= m_Graph.m_nVexNum || end_place < 0 || end_place >= m_Graph.m_nVexNum) {
cout << "输入错误!请重新输入!!!" << endl;
return;
}
Edge aPath[20]; //边信息数组,依次保存最短的路径
for (int i = 0; i < 20; i++) { //初始化边信息数组
aPath->vex1 = -1;
aPath->vex2 = -1;
aPath->weight = -1;
}
//搜索最短路径
int index = FindShortPath(start_place, end_place, aPath);
int length = 0; //最短路径总长度
Vex sVex = GetVex(aPath[0].vex1);
//得到最短路径和最短距离
cout << "n最短路径为:" << sVex.name;
for (int i = 0; i < index; i++) {
sVex = GetVex(aPath[i].vex2);
cout << "->" << sVex.name;
length += aPath[i].weight;
}
cout << endl;
cout << "最短距离为:" << length << "米" << endl << endl;
}
//函数名:DesignPath
//功能:查询电路铺设规划图
//参数:void
//返回值:void
void DesignPath()
{
cout << "在以下两个景点之间铺设电路";
cout << "n=======铺设电路规划=======" << endl;
Edge aPath[20];
FindMinTree(aPath); //构建最小树
int nVexNum = m_Graph.m_nVexNum;
if (nVexNum == 0) {
cout << "请先创建图!" << endl;
return;
}
//输出铺设线路图
int nAllLength = 0;
for (int i = 0; i < m_Graph.m_nVexNum - 1; i++) {
Vex nVex1 = GetVex(aPath[i].vex1);
Vex nVex2 = GetVex(aPath[i].vex2);
cout << "t" << nVex1.name << "-" << nVex2.name << ":" << aPath[i].weight << "m" << endl;
nAllLength += aPath[i].weight;
}
cout << "==========================n";
cout << "铺设电路的总长度是:" << nAllLength << "m" << endl << endl;
}
3.5、Tourism.h
#pragma once
//读取文件,创建景区景点图
void CreateGraph(void);
//调用GetVex()函数,得到所有顶点信息并输出
void GetSpotInfo(void);
//通过调用DFSTraverse()函数,实现旅游景点导航功能,将查询到的景点导航路线显示在界面上
void TravelPath();
//调用Graph.cpp文件中的FindShortPath函数查询两个景点间的最短路径和距离
void FindShortPath(void);
//查询铺设电路规划图
void DesignPath();
最后
以上就是务实战斗机为你收集整理的[数据结构与算法综合实验]图与景区信息管理系统一、实验任务二、效果展示三、源码的全部内容,希望文章能够帮你解决[数据结构与算法综合实验]图与景区信息管理系统一、实验任务二、效果展示三、源码所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复