文章目录
实验目的
掌握图的存储结构和定义
掌握图的创建方法和图的应用
掌握图的两种遍历方法和应用
掌握迪杰斯特拉算法和应用
理解最小生成树的概念
掌握普里姆算法和应用 使用 C++、定义图的数据结构,结合迭代开发思路实现“景区信息管理”专题编程。
主要仪器设备及耗材
1.安装了Windows 10操作系统的PC机1台
2.PC机系统上安装了Microsoft Visual Studio 2019开发环境
以下是本篇文章正文内容,下面案例可供参考
一、实验要求
开发景区信息管理系统,对景区的信息进行整理。使用图的数据结构来保存景区景点信息,为用户提供创建图,查询景点信息,旅游景点导航,搜索最短路径,铺设电路规划等功能。在确保书上例子正确的情况下,添加自己创建的图来检查自己实现的功能。
二、分析与设计
依据上述的实验目的与要求,可导出实现的图与景区信息管理系统的流程为:
(1)创建图:从Vex.txt和Edge.txt中分别读取景点信息和道路信息,根据读取的景区信息创建景区景点图。
(2)查询景点:根据输入的景点编号,查询该景点及相邻景点的信息。
(3)旅游景点导航:从起始景点开始,遍历景区所有景点,记录所有无重复的路径。
(4)搜索最短路径:搜索两个景点之间的所有路径,找到其中距离最短的路径。
(5)铺设电路规划:根据景区景点图,构造一棵最小生成树,设计出一套铺设线路最短,但能满足每个景点都能通电的方案。
1.数据结构的设计
代码如下(示例):
//定义Vex结构体,存储图的顶点
struct Vex
{
int num;//景区编号
char name[20];//景点名字
char desc[1024];//景点介绍
};
//定义Edge结构体,存储边的信息
struct Edge
{
int vex1;//边的第一个顶点
int vex2;//边的第二个顶点
int weight;//权值
};
//定义图的存储结构
struct Graph
{
int m_aAdjMatrix[20][20];//邻接矩阵
Vex m_Vexs[20];//顶点信息数组
int m_nVexNum;//当前图的顶点个数
};
//定义链表来保存所有路径
typedef struct Path {
int vexs[20];//保存一条路径
Path* next;//下一条路径
}*PathList;
2.核心算法设计
改进DFS算法
代码如下(示例):
void DFS(int nVex, bool bVisited[], int& nIndex, PathList& pList) {
bVisited[nVex] = true;//该顶点被遍历
pList->vexs[nIndex++] = nVex;//访问顶点编号为nVex的顶点
//判断所有的顶点是否都已经被访问过
int vexnum = 0;
for (int i = 0; i < m_Graph.m_nVexNum; i++)
//如果当前i节点被访问过,则vexNum自加
if (bVisited[i]) vexnum++;
//如果所有的顶点都已经被访问过,就保存这一条路径
if (vexnum == m_Graph.m_nVexNum)
{
//创建一个新链表,将当前的pList中的数据保存起来
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指针继续往下移动,寻找下一条路径
pList->next = NULL; //pList->next赋值为空
}
//若没有全部访问,则继续访问下一个相邻节点
else
{
for (int i = 0; i < m_Graph.m_nVexNum; i++)//搜索nVex的所有邻接点
{
if (!bVisited[i] && m_Graph.m_aAdjMatrix[nVex][i] > 0)//i是nVex的邻接点
{
DFS(i, bVisited, nIndex, pList); //递归调用DFS
bVisited[i] = false; //未访问
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)
//初始化该顶点到其他顶点的最短距离
nShortDistance[v] = m_Graph.m_aAdjMatrix[nVexStart][v];
else
//如果顶点v和nVexStart不相连,设置之间的距离为最大值
nShortDistance[v] = 0x7FFFFFFF;
nShortPath[v][0] = nVexStart; //起始点为nVexStart
//初始化最短路径
for (int w = 1; w < m_Graph.m_nVexNum; w++) nShortPath[v][w] = -1;
}
aVisited[nVexStart] = true;//将nVexStart顶点算在最短路径中
int min; //存放路径的最小值
for (int i = 1; i < m_Graph.m_nVexNum; i++)
{
min = 0x7FFFFFFF;
bool addon = false; //判断是否还有顶点可以加入最短路径
for (int w = 0; w < m_Graph.m_nVexNum; w++)
{
if (nShortDistance[w] < min &&!aVisited[w] )//w是距离nVexStart最近的点且w不在原先的最短路径中
{
v = w; //w顶点距离nVexStart顶点最近
min = nShortDistance[w]; //w到nVexStart的最短距离为min
addon = true; //有顶点加入最短路径
}
}
//如果没有顶点可以加入到最短路径,则跳出循环
if (!addon) break;
aVisited[v] = true; //将w顶点加入到最短路径
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;
}
Prim算法(构建最小生成树)
//通过Prim算法来构建最小生成树
void FindMinTree(Edge aPath[]) {
bool aVisited[20] = {
false }; //判断某顶点是否在最小生成树中,false表示不在
aVisited[0] = true; //从0号顶点开始,加入到最小生成树中
int min;
int nVex1=0, nVex2=0;
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.测试用例设计
使用书上例子,观察每个功能是否与书上有相同的结果。
使用自己创建的景点图,观察是否出现错误和结果是否合理。
4.测试结果
总结
详情可参考以下链接
链接:冲冲冲~
提取码:fv2n
复制这段内容后打开百度网盘手机App,操作更方便哦