校园导航系统
【问题描述】
当对校园参观时,会遇到这样的问题:如果从校园的某个位置出发,参观到校园中的所有景点,怎样设计路线,使参观者既能参观所有景点又使走的路程最少。
【数据描述】
定义一个邻接矩阵存储结构,用来存储点和边的信息。
定义一个辅助数组closedge,该数组包含两个分量,lowcost记录从U到V-U具有最小代价的边,adjvex记录改边依附于U中的顶点。
typedef char ElemType;
typedef struct {
ElemType vexs[max];
int arcs[max][max];
int vexnum,arcnum;
}MGraph;
struct {
ElemType adjvex;
int lowcost;
}closedge[max];
【算法思想】
(1)已知校园中各景点和路径的权重,使参观者既能参观所有景点又使走的路程最少。即求最小生成树,使得路径保持连通且经过所有边权值之和最小。
(2)用到Prim算法求最小生成树,算法思想大体为:
设N=(V,E)是一个连通网,T=(U,TE)是N的最小生成树,TE是N中最小生成树中边的集合。
①初始化:令U={u0|u0∈V},TE={}。其中u0是顶点集合V中的某个顶点。
②选择:在所有u∈U,v∈V-U的边(u,v)∈E中,选择一条代价最小的边(ui,vj),将(ui,vj)并入集合TE,同时vj并入U。
③反复执行步骤②,直至U=V为止。
TE必有n-1条边,则T为N的最小生成树。
【C源程序】
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define max 20
#define INFINITY 1000
typedef char ElemType;
typedef struct {
ElemType vexs[max];
int arcs[max][max];
int vexnum,arcnum;
}MGraph;
struct {
ElemType adjvex;
int lowcost;
}closedge[max];
//返回顶点下标
int LocateVex(MGraph G,ElemType v)
{
for(int i=0;i<G.vexnum;i++)
{
if(v==G.vexs[i])
return i;
}
return -1;
}
//建立无向图邻接矩阵
void CreatGraph(MGraph &G)
{
int i, j, k,m,n;
char v1, v2;
srand(time(0));
printf("输入校园中景点数及弧数:\n");
scanf( "%d%d", &G.vexnum, &G.arcnum );
getchar();
printf("输入校园中所有景点:\n" );
for( i=0; i<G.vexnum; i++ )
{
G.vexs[i]=getchar();
getchar(); }
for( i=0; i<G.vexnum; i++ ) //初始化邻接矩阵
for( j=0; j<G.vexnum; j++ )
G.arcs[i][j]=INFINITY;
for( k=0; k<G.arcnum; k++ )
{
int w;
printf("输入校园中的两个景点确定边:\n" );
v1=getchar(); getchar();
v2=getchar(); getchar();
m= LocateVex(G,v1); n= LocateVex(G,v2);
printf("请输入边的权重:\n");
scanf("%d",&w);
getchar();
G.arcs[m][n]=w;G.arcs[n][m]=w;
}
printf("邻接矩阵为:\n");
for( i=0; i<G.vexnum; i++ )
{
for( j=0; j<G.vexnum; j++ )
printf("%d\t",G.arcs[i][j]);
printf("\n");
}
}
//Prim(适用于边稠密的网)
int MiniSpanTree_Prim(MGraph G,ElemType u)
{
int k=LocateVex(G,u);
for(int j=0;j<G.vexnum;j++)
{
if(j!=k)
{
closedge[j].adjvex=u;
closedge[j].lowcost=G.arcs[k][j];
}
}
closedge[k].lowcost=0;
int minsum=0;
for(int i=1;i<G.vexnum;i++)
{
int minCost=INFINITY;
for(int j=0;j<G.vexnum;j++)//找最小值
{
if(closedge[j].lowcost!=0&&closedge[j].lowcost<minCost){
minCost = closedge[j].lowcost;
k=j;
}
}
printf("%c----%c %d\n",closedge[k].adjvex,G.vexs[k],closedge[k].lowcost);
minsum+=closedge[k].lowcost;
closedge[k].lowcost=0;
for(int j=0;j<G.vexnum;j++)
{
if(closedge[j].lowcost!=0&&G.arcs[k][j]<closedge[j].lowcost)
{
closedge[j].adjvex = G.vexs[k];
closedge[j].lowcost = G.arcs[k][j];
}
}
}
return minsum;
}
int main()
{
MGraph G;
CreatGraph(G); //建立无向图的邻接矩阵
printf("请输入从哪个景点出发:\n");
char u;
scanf("%c",&u);
printf("\n 最短路径权重之和为;%d.\n", MiniSpanTree_Prim(G,u));//输出路径与权值
return 0;
}
【小结】
校园导航问题:
不足之处:将问题过于简单化,就简单实现建立赋权图的邻接矩阵存储结构,和用Prim算法求最短生成树,跟校园导航没有太多关系,不实用。
通过进行数据结构课程设计,对数据结构和算法有了进一步深刻的认识。也发现了自己很多问题。对许多重要的算法不能熟练的运用。仍需对代码进一步完善。
【参考文献】
[1] 赵永升,宋丽华,数据结构.北京:电子工业出版社,2019.
[2] 严蔚敏,数据结构(C语言版).北京:清华大学出版社,2007.