实验内容:
面向学校,构建一个校院导游软件。用无向图表示所在学校的校院景点平面图,图中顶点表示主要景点,存放景点的编号、名称、简介等信息,图中边表示景点之间的道路,存放路径距离等信息。该软件具有以下基本功能,学生可自行扩展功能。
1)查询各景点的详细信息;
2)查询图中任意两个景点之间的所有可能路径;
3)查新图中任意两个景点之间的最短路径;
4)增加、删除、更新景点与道路信息
实验步骤:
(1)按照实验要求编写代码,构造导游软件系统。
(2)输入验收用例,验证其输出结果。
#include <iostream>
#include<string.h>
using namespace std;
#define MVNum 100
#define MAXDIS 368789
typedef struct ArcNode
{
double distance;
ArcNode *nextarc;
int adjvex;
};
int *visit;
typedef struct VNode
{
int number;
string name;
string resume;
ArcNode *firstarc;
} VNode,AdjList[MVNum];
struct road
{
int startPoint;
int endPoint;
double distance;
};
struct AGraph
{
AdjList adjlist;
double adjmatrix[MVNum][MVNum];
int vexnum,arcnum;
};
int LocateVex(AGraph G,int v)
{
for(int i =0; i<G.vexnum; i++)
{
if(G.adjlist[i].number==v) return i;
}
return -1;
}
void createvisit(int* &visit,int vexnum)
{
visit = new int[vexnum];
for(int i = 0; i < vexnum; i++)
{
visit[i] = 0;
}
}
//构建无向图的邻接表
void CreateUDG(AGraph &G)
{
G.vexnum=7;
G.arcnum=10;
createvisit(visit,G.vexnum);
G.adjlist[0].number=0;
G.adjlist[0].name="材料重点实验室";
G.adjlist[0].resume="国家重点实验室";
G.adjlist[0].firstarc=NULL;
G.adjlist[1].number=1;
G.adjlist[1].name="计算机学院";
G.adjlist[1].resume="计算机上课的地方";
G.adjlist[1].firstarc=NULL;
G.adjlist[2].number=2;
G.adjlist[2].name="志义体育场";
G.adjlist[2].resume="运动会举办的地方";
G.adjlist[2].firstarc=NULL;
G.adjlist[3].number=3;
G.adjlist[3].name="图书馆";
G.adjlist[3].resume="河南存储书最多的地方";
G.adjlist[3].firstarc=NULL;
G.adjlist[4].number=4;
G.adjlist[4].name="综合教学楼";
G.adjlist[4].resume="学校主要上课的地方";
G.adjlist[4].firstarc=NULL;
G.adjlist[5].number=5;
G.adjlist[5].name="物理学院";
G.adjlist[5].resume="全校物理实验的上课地方";
G.adjlist[5].firstarc=NULL;
G.adjlist[6].number=6;
G.adjlist[6].name="创业中心";
G.adjlist[6].resume="最受学生喜欢的地方";
G.adjlist[6].firstarc=NULL;
//初始化邻接矩阵
for (int i = 0; i<G.vexnum; i++)
{
for(int j = 0; j<G.vexnum; j++)
{
G.adjmatrix[i][j]=MAXDIS;
// if(i==j) G.adjmatrix[i][j]=0;
}
}
//road1用于最初的图形初始化
road road1[] = {{0,1,30},{1,3,10},{1,2,20},{1,4,10},{3,5,40},{3,4,5},{4,5,30},{2,4,30},{4,6,5},{5,6,50}};
for(int k=0; k<G.arcnum; k++)
{
int number1,number2;
double weight;
number1 = road1[k].startPoint;
number2 = road1[k].endPoint;
weight=road1[k].distance;
//将景点编号转为下标
int i = LocateVex(G,number1);
int j = LocateVex(G,number2);
G.adjmatrix[i][j]=weight;
G.adjmatrix[j][i]=weight;
ArcNode *p1 = new ArcNode;
p1->adjvex =j;
p1->distance=weight;
p1->nextarc = G.adjlist[i].firstarc;
G.adjlist[i].firstarc=p1;
ArcNode *p2 = new ArcNode;
p2->distance=weight;
p2->adjvex=i;
p2->nextarc=G.adjlist[j].firstarc;
G.adjlist[j].firstarc=p2;
}
}
//该算法使用前需要设置一个visit数组,且全部为0,vi是起点,vj是终点
void FindPath(AGraph g,int vi,int vj,int path[],int d)
{
ArcNode *p;
visit[vi]=1;
path[++d]=vi;
if(vi==vj)
{
for(int i = 0; i<=d; i++)
{
cout << g.adjlist[path[i]].name<<" ";
}
cout << endl;
}
p=g.adjlist[vi].firstarc;
while(p)
{
if(visit[p->adjvex]==0) FindPath(g,p->adjvex,vj,path,d);
p = p->nextarc;
}
visit[vi]=0;
}
void Floyd(AGraph g,int path[MVNum][MVNum],int map[MVNum][MVNum])
{
int n = g.vexnum;
for(int i=1; i<=g.vexnum; i++)
{
for(int j=1; j<=n; j++)
{
if(i==j)
map[i][j]=0;
else
map[i][j]=MAXDIS;
}
}
for(int i=0; i<n; i++)
{
for(int j=0; j<n; j++)
{
if(g.adjmatrix[i][j]!=MAXDIS)
{
map[i+1][j+1]=g.adjmatrix[i][j];
map[j+1][i+1]=g.adjmatrix[i][j];
path[i+1][j+1]=j+1;
}
}
}
//计算最短距离
for(int k=1; k<=n; k++)
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
if(map[i][k]+map[k][j]<map[i][j])
{
map[i][j]=map[i][k]+map[k][j];
path[i][j]=path[i][k];
}
int v1,v2,z;
cout<<"输入两个景点编号,输出最短路径"<<endl;
cin>>v1>>v2;
v1=LocateVex(g,v1);
v2=LocateVex(g,v2);
if(v1==-1||v2==-1) return;
v1=v1+1;
v2=v2+1;
z=path[v1][v2];
cout<<g.adjlist[v1-1].name;
while(z!=v2)
{
cout<<"->"<<g.adjlist[z-1].name;
z=path[z][v2];
}
cout<<"->"<<g.adjlist[v2-1].name;
}
void addV(AGraph &g,int n,int vi,int distance){
cout << "请输入增加顶点的名称以及简介:";
//邻接表增加
cin >>g.adjlist[g.vexnum].name;
cin >> g.adjlist[g.vexnum].resume;
g.adjlist[g.vexnum].firstarc=NULL;
g.adjlist[g.vexnum].number=g.adjlist[g.vexnum-1].number+1;
g.vexnum=g.vexnum+1;//景点数+1
//边表增加
cout << endl<<"请输入景点的道路数目:";
cin >> n;
g.arcnum=g.arcnum+n;//边数+n
cout << endl<<"请输入每条道路以该景点为起点所能到达的景点编号以及距离:"<<endl;
//邻接矩阵初始化
for(int i = 0; i<g.vexnum; i++)
{
g.adjmatrix[g.vexnum-1][i]=MAXDIS;
g.adjmatrix[i][g.vexnum-1]=MAXDIS;
}
//创建边
for(int i=0; i<n; i++)
{
cin >> vi >> distance;
ArcNode *p1 = new ArcNode;
p1->adjvex =vi;
p1->distance=distance;
p1->nextarc = g.adjlist[g.vexnum-1].firstarc;
g.adjlist[g.vexnum-1].firstarc=p1;
g.adjmatrix[g.vexnum-1][vi]=distance;
g.adjmatrix[vi][g.vexnum-1]=distance;
ArcNode *p2 = new ArcNode;
p2->distance=distance;
p2->adjvex=g.vexnum-1;
p2->nextarc=g.adjlist[vi].firstarc;
g.adjlist[vi].firstarc=p2;
}
//删除景点
}
void deleteV(int vi,AGraph &g){
//修改邻接矩阵
for(int i=vi+1; i<g.vexnum; i++)
{
for(int j=0; j<g.vexnum; j++)
{
g.adjmatrix[i-1][j]=g.adjmatrix[i][j];
}
for(int j=0; j<g.vexnum; j++)
{
g.adjmatrix[j][i-1]=g.adjmatrix[j][i];
}
}
//修改邻接表
for(int i=0; i<g.vexnum; i++)
{
//边指针
ArcNode *p=g.adjlist[i].firstarc;
//一条边的处理情况
if(p->nextarc==NULL)
{
if(p->adjvex==vi)
{
g.adjlist[i].firstarc=NULL;
g.arcnum=g.arcnum-1;
}
}
//没有边
else if(p==NULL) continue;
//多条边
else
{
//如果是首元结点
if(p->adjvex==vi)
{
g.adjlist[i].firstarc=p->nextarc;
g.arcnum=g.arcnum-1;
continue;
}
//不是首元结点
while(p->nextarc&&p->nextarc->adjvex!=vi)
{
p=p->nextarc;
}
if(p->nextarc)
{
p->nextarc=p->nextarc->nextarc;
g.arcnum=g.arcnum-1;
}
}
}
for(int i=vi; i<g.vexnum-1; i++)
{
g.adjlist[i]=g.adjlist[i+1];
}
g.vexnum=g.vexnum-1;
}
void show(AGraph g){
for(int i = 0; i <g.vexnum; i++)
{
cout << "编号:"<<g.adjlist[i].number<<"\t名称:"<<g.adjlist[i].name<<"\t简介:"<<g.adjlist[i].resume<<endl;
}
}
void addPath(AGraph &g,int vi,int vj,int distance){
cout << "请输入该路径长度:"<<endl;
cin >> distance;
g.adjmatrix[vi][vj]=distance;
g.adjmatrix[vj][vi]=distance;
ArcNode *p1 = new ArcNode;
p1->adjvex =vj;
p1->distance=distance;
p1->nextarc = g.adjlist[vi].firstarc;
g.adjlist[vi].firstarc=p1;
ArcNode *p2 = new ArcNode;
p2->distance=distance;
p2->adjvex=vi;
p2->nextarc=g.adjlist[vj].firstarc;
g.adjlist[vj].firstarc=p2;
g.arcnum=g.arcnum+1;
}
void alterV(int vi,AGraph &g){
cout << "请输入要修改的景点编号:";
cin >> vi;
vi = LocateVex(g,vi);
cout << "请输入修改后的景点名称以及简介:";
cin >> g.adjlist[vi].name;
cin >> g.adjlist[vi].resume;
}
void deletePath(AGraph &g,int vi,int vj){
g.adjmatrix[vi][vj]=MAXDIS;
g.adjmatrix[vj][vi]=MAXDIS;
ArcNode *p=g.adjlist[vi].firstarc;
//一条边的处理情况
if(p->nextarc==NULL)
{
if(p->adjvex==vj)
{
g.adjlist[vi].firstarc=NULL;
g.arcnum=g.arcnum-1;
}
}
//多条边
else
{
//如果是首元结点
if(p->adjvex==vj)
{
g.adjlist[vi].firstarc=p->nextarc;
g.arcnum=g.arcnum-1;
}
//不是首元结点
while(p->nextarc&&p->nextarc->adjvex!=vj)
{
p=p->nextarc;
}
if(p->nextarc)
{
p->nextarc=p->nextarc->nextarc;
g.arcnum=g.arcnum-1;
}
}
p=g.adjlist[vj].firstarc;
//一条边的处理情况
if(p->nextarc==NULL)
{
if(p->adjvex==vi)
{
g.adjlist[vj].firstarc=NULL;
g.arcnum=g.arcnum-1;
}
}
//多条边
else
{
//如果是首元结点
if(p->adjvex==vi)
{
g.adjlist[vj].firstarc=p->nextarc;
g.arcnum=g.arcnum-1;
}
//不是首元结点
while(p->nextarc&&p->nextarc->adjvex!=vi)
{
p=p->nextarc;
}
if(p->nextarc)
{
p->nextarc=p->nextarc->nextarc;
g.arcnum=g.arcnum-1;
}
}
}
void alterPath(AGraph &g,int distance,int vi,int vj){
cout << "请输入修改后的路径长度"<<endl;
cin >> distance;
g.adjmatrix[vi][vj]=distance;
g.adjmatrix[vj][vi]=distance;
ArcNode *p=g.adjlist[vi].firstarc;
while(p->adjvex!=vj) p=p->nextarc;
p->distance=distance;
p=g.adjlist[vj].firstarc;
while(p->adjvex==vi) p=p->nextarc;
p->distance=distance;
}
void home()
{
cout <<" | <河南大学校园导航> |"<<endl;
cout <<" | 1.校园景点 |"<<endl;
cout <<" | 2.查询路径 |"<<endl;
cout <<" | 3.最短路径 |"<<endl;
cout <<" | 4.增加景点 |"<<endl;
cout <<" | 5.删除景点 |"<<endl;
cout <<" | 6.修改景点 |"<<endl;
cout <<" | 7.增加路径 |"<<endl;
cout <<" | 8.删除路径 |"<<endl;
cout <<" | 9.修改路径 |"<<endl;
cout <<" | 10.退出导航 |"<<endl;
}
int main()
{
AGraph g;
CreateUDG(g);
int path[g.vexnum];
int path1[MVNum][MVNum];
int map[MVNum][MVNum];
int vi,vj;
int distance;
int choice;
int n;
home();
while(1)
{
cout << "请输入您的需求:";
cin >> choice;
switch(choice)
{
case 1:
//查询各景点信息
show(g);
break;
//查询任意路径
case 2:
cout << "请依次输入初始景点编号及终点景点编号:";
cin >> vi >> vj;
vi = LocateVex(g,vi);
vj = LocateVex(g,vj);
if(vi==-1||vj==-1) break;
cout << endl;
FindPath(g,vi,vj,path,-1);
break;
//最短路径
case 3:
Floyd(g,path1,map);
cout << endl;
break;
//增加景点
case 4:
addV(g,n,vi,distance);
break;
case 5:
cout << "请输入景点编号:";
cin >> vi;
vi = LocateVex(g,vi);
if(vi==-1) break;
deleteV(vi,g);
break;
//修改景点
case 6:
alterV(vi,g);
break;
//增加路径
case 7:
{
cout << "请输入路径两端景点编号:"<<endl;
cin >>vi >> vj;
vi = LocateVex(g,vi);
vj = LocateVex(g,vj);
if(vi==-1||vj==-1) break;
addPath(g,vi,vj,distance);
}
break;
//删除路径
case 8:
cout << "请输入路径两端景点编号:"<<endl;
cin >>vi >> vj;
vi = LocateVex(g,vi);
vj = LocateVex(g,vj);
if(vi==-1||vj==-1) break;
deletePath(g,vi,vj);
break;
case 9:
cout << "请输入路径两端景点编号:"<<endl;
cin >>vi >> vj;
vi = LocateVex(g,vi);
vj = LocateVex(g,vj);
if(vi==-1||vj==-1) break;
alterPath(g,distance,vi,vj);
break;
case 10:
return 0;
break;
}
cout <<endl;
}
return 0;
}