学校的校园景点平面图(校园景点迷你地图C++&数据结构)
设计要求:
(1)建图
以图中顶点表示主要景点,并存放景点的编号、名称、简介等信息;
(2)查询
该系统可以查询景点的信息;
查询图中任意两个景点间的最短路径;
查询图中所有景点间的最短路径;
查询图中任意两个景点间的所有路径。
(3)更新
更新景点间路径长度;
在两个景点之间添加一条路径;
删除两个景点之间的一条路径;
增添一个景点;
去除一个景点;
更改景点的简介。
功能实现
(1)建图
首先画出所要建立的地图的形象版
为了方便使用图论的知识来完成上述所要实现的功能,将这个形象图抽象化,变成图:
邻接矩阵1:(由createMTGraph()函数建立的邻接矩阵)
邻接矩阵2:(由createMTGraph1()函数建立的邻接矩阵)
接下来使用数据结构的知识用编程语言表示这个图:
#define numedges 100 //最大边数
#define numvertices 13 //最大顶点个数
typedef string vertexdata; //顶点数据类型
typedef int edgedata; //边上权值类型
typedef int *listofnode;
typedef struct node{
vertexdata verlist[numvertices]; //顶点表,verlist[i]类型为string,存放顶点名称
vertexdata info[numvertices];//存放顶点简介
edgedata edge[numvertices][numvertices]; //邻接矩阵--边表,可视为边之间的关系,存放权值
int n,e;//图中当前的顶点个数与边数
}MTGraph;
这是使用邻接矩阵表示有向图。
注:为什么刚才抽象出来的图是无向图,而我要使用有向图呢?
因为分析这个地图要实现的功能,有“查询图中任意两个景点间的最短路径; 查询图中所有景点间的最短路径;查询图中任意两个景点间的所有路径。”,这些功能一定会用到那个著名的算法:Floyd算法,而这个算法是要求使用有向图的;而且使用邻接矩阵表示的图,无论是有向图还是无向图,都是可以互相转化的,简单地说就是:双向有向图==无向图,即把有向图每对顶点之间的有向边都变为两条方向相反的有向边!这也不会费多少功夫和资源。
(2)对该图的一些基本操作:
//判断两个顶点之间是否有边
bool isEdge(MTGraph &G,int v1,int v2){
return G.edge[v1][v2]!=INF;
}
//创建一个新的顶点
void newnode(MTGraph &G,vertexdata v){
G.verlist[G.n]=v;//G.n=11
G.n++;//G.n=12
for(int i=0;i<G.n+1;i++){
//i<12 (i:0~11)
G.edge[G.n-1][i]=INF;
G.edge[i][G.n-1]=INF;
}
}
//更改两个景点v1,v2之间的路径长度为juli
void chg(MTGraph &G,int v1,int v2,int juli){
if(isEdge(G,v1,v2)){
int temp=G.edge[v1][v2];
G.edge[v1][v2]=juli;
G.edge[v2][v1]=juli;
cout<<G.verlist[v1]<<"和"<<G.verlist[v2]<<"这两个景点之间的路径长度从"<<temp<<"更改为"<<juli<<endl;
}
else{
cout<<"这两个景点之间没有直接路径,更新失败!"<<endl;
//return;
}
}
//删除一个顶点
void delnode(MTGraph &G,int v){
int i,j;
for(i=0;i<G.n;i++)
if(G.edge[v][i]!=INF){
G.edge[v][i]=INF;
G.edge[i][v]=INF;
G.e==G.e-2;
}// 删除一个顶点 之后表示该图的邻接矩阵 也会改变
for(i=v+1;i<G.n;i++)//行
for(j=0;j<G.n;j++)//列
G.edge[i-1][j]=G.edge[i][j];
for(i=v+1;i<G.n;i++)//列
for(j=0;j<G.n-1;j++)//行
G.edge[j][i-1]=G.edge[j][i];
for(i=v+1;i<G.n;i++)
G.verlist[i-1]=G.verlist[i];
G.n--;
}
//添加1条V1->V2的有向边(建立图时用)
void setsucc1(MTGraph &G,int v1,int v2,int w){
if(isEdge(G,v1,v2))
return;
G.e++;
G.edge[v1][v2]=w;
//G.edge[v2][v1]=w;
}
//在V1和V2这两个景点之间添加一条路径(添加路径时用)
void setsucc2(MTGraph &G,int v1,int v2,int w){
if(isEdge(G,v1,v2)){
cout<<G.verlist[v1]<<"和"<<G.verlist[v2]<<"这两个景点之间已经存在路径,不需要在添加路径!"<<endl;
return;
}
G.e++;
G.edge[v1][v2]=w;
G.edge[v2][v1]=w;
cout<<"成功在"<<G.verlist[v1]<<"和"<<G.verlist[v2]<<"这两个景点之间添加一条长度为"<<w<<"的路径"<<endl;
}
//删除V1->V2的和V2->V1的边;删除V1和V2这两个景点之间的一条路径
void delsucc(MTGraph &G,int v1,int v2){
if(!isEdge(G,v1,v2)){
cout<<G.verlist[v1]<<"和"<<G.verlist[v2]<<"这两个景点之间不存在路径,不需要在删除路径!"<<endl;
return;
}
int temp=G.edge[v1][v2];
G.e--;
G.edge[v1][v2]=INF;
G.edge[v2][v1]=INF;
//G.edge[v1][v2]=0;
//G.edge[v2][v1]=0;
cout<<"成功删除"<<G.verlist[v1]<<"和"<<G.verlist[v2]<<"这两个景点之间一条长度为"<<temp<<"的路径"<<endl;
}
//v的直接后继
int *succ(MTGraph G,int v){
int *ret=new int[numvertices];
int i,k;
for(i=0;i<G.n;i++){
if(G.edge[v][i])
ret[k++]=i;
}
ret[k]=-1