我是靠谱客的博主 务实战斗机,最近开发中收集的这篇文章主要介绍[数据结构与算法综合实验]图与景区信息管理系统一、实验任务二、效果展示三、源码,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

文章目录

  • 一、实验任务
    • 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. 这些道路都是可以双向行驶的(无向图)
  3. 从任意一个景点出发都可以游览整个景区(连通图)

开发景区信息管理系统,对景区的信息进行管理。使用图的数据结构来保存景区景点 信息,为用户提供创建图、查询景点信息、旅游景点导航、搜索最短路径、铺设电路规划等功能

1.2、景点数据

景区的数据包含景点信息和景点之间的道路信息,分别由两个文本文件存储

  1. Vex.txt 文件用来存储景点信息
7
0
A区
风景优美,气候宜人。门票10元。
1
B区
风景优美,气候宜人。门票20元。
2
C区
风景优美,气候宜人。门票30元。
3
D区
风景优美,气候宜人。门票40元。
4
E区
风景优美,气候宜人。门票50元。
5
F区
风景优美,气候宜人。门票60元。
6
G区
风景优美,气候宜人。门票70元。
  1. 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();

最后

以上就是务实战斗机为你收集整理的[数据结构与算法综合实验]图与景区信息管理系统一、实验任务二、效果展示三、源码的全部内容,希望文章能够帮你解决[数据结构与算法综合实验]图与景区信息管理系统一、实验任务二、效果展示三、源码所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(42)

评论列表共有 0 条评论

立即
投稿
返回
顶部