河北大学校园导航
【问题描述】
以我校为例,设计一个校园导航系统,主要为来访的客人提供信息查询。系统有两类登陆账号,一类是游客,使用该系统方便校内路线查询;一类是管理员,可以使用该系统查询校内路线,可对校园景点路线可编辑。
【需求分析】
设计学校的平面图,至少包括10个以上景点(场所),每两个景点间可以有不同道路,且路长也可能不同,找出在游人所在景点到其他景点的最短路径,或游人输入的任意两个景点的最短路径。 要求: (1) 以图中顶点表示校园内各景点,存放景点名称、代号、简介等信息;以边表示路径,路径权重为路径长度。 (2) 为游人提供任意景点相关信息查询。 (3)为游人提供任意景点的问路查询,即任意两个景点之间的最短路径。
实现提示: 一般情况下,校园道路是双向通行的,可设计校园平面图是一个无向图。顶点和边均含有相关信息。 选做内容: (1)提供图的编辑功能:增删景点;增删道路;修改已有信息等。 (2)校园导游图的仿真界面。
后续操作自行操作即可
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#define INF 9999
typedef struct
{
char name[20];
char features[100];
} Vertex;
//矩阵结构体
typedef struct
{
Vertex vexs[100];
int edges[500][500];
int n,e;//点和边数
} Graph;
//构造图的矩阵存储
void create(Graph *G )
{
int i,j;
G->n=12;
G->e=20;
char str_name[50][50]= {"体检中心","邯郸音乐厅","网计学院","信息学部","操场","图书馆",
"花园景观","校门南口","校门北口","校门东口","银杏景观","餐厅"
};
char str_features[100][200]= {"学校的用于学生体检地","学校用于举办大型音乐会的地方","C1楼","信息学部","操场","图书馆","用于观赏",
"校门南口","校门北口","校门东口","种植了许多银杏树","餐厅"
};
for(i=0; i<G->n; i++)//节点信息初始化
{
strcpy(G->vexs[i].name,str_name[i]);
strcpy(G->vexs[i].features,str_features[i]);
}
for(i=0; i<500; i++)
for(j=0; j<500; j++)
G->edges[i][j]=INF;
G->edges[1][0]=G->edges[0][1]=200;
G->edges[4][0]=G->edges[0][4]=350;
G->edges[1][2]=G->edges[2][1]=500;
G->edges[2][7]=G->edges[7][2]=400;
G->edges[1][4]=G->edges[4][1]=480;
G->edges[1][5]=G->edges[5][1]=400;
G->edges[1][3]=G->edges[3][1]=500;
G->edges[7][3]=G->edges[3][7]=400;
G->edges[6][3]=G->edges[3][6]=150;
G->edges[7][6]=G->edges[6][7]=500;
G->edges[7][9]=G->edges[9][7]=600;
G->edges[4][5]=G->edges[5][4]=280;
G->edges[4][8]=G->edges[8][4]=200;
G->edges[5][6]=G->edges[6][5]=160;
G->edges[5][9]=G->edges[9][5]=300;
G->edges[6][9]=G->edges[9][6]=200;
G->edges[9][11]=G->edges[11][9]=100;
G->edges[8][11]=G->edges[11][8]=100;
G->edges[8][10]=G->edges[10][8]=100;
G->edges[10][11]=G->edges[11][10]=100;
}
//遍历景点
int ergodic(Graph *G,int v)
{
int i;
for(i=0; i<G->n; i++)
{
if(i==v)
return v;
}
return -1;
}
void display(Graph *G)
{
int k=-1;
int i,j;
printf("\n\n");
for( i=0;i<=G->n;i++){
printf("\n");
for(j=0;j<=G->n;j++){
if(G->edges[i][j]<INF){
printf("%d ",G->edges[i][j]);
}else if(i==j)
{
printf(" 0 ");
}
else{
printf(" ∞ ");
}
}
}
printf("\n\n");
}
//任意景点的介绍
Vertex GetVex(Graph *G, int v)
{
int j;
j=ergodic(G,v);
if(j==-1)
{
printf(" 无此景点\n\n\n\n");
Sleep(1000);
return ;
}
else
{
printf("%s",G->vexs[v].name);
Vertex a=G->vexs[j];
return a;
}
}
//修改景点信息
void PutVertex(Graph *G, int v)
{
int j;
j=ergodic(G,v);
if(j==-1)
{
printf(" 无此景点\n\n\n\n\n");
Sleep(1000);
}
else
{
char s[100];
printf("\n");
printf(" 请输入修改后的信息:\n\n");
printf(" ");
scanf("%s",s);
strcpy(G->vexs[j].features,s);
printf("\n");
printf(" 修改成功\n\n\n\n\n");
}
}
//增加景点
void InsertVertex(Graph*G, Vertex v)
{
char str_name[20],str_features[100];
int num,edge,a[100],i,a1[100],b;
printf(" 请输入景点名称:\n\n");
printf(" ");
scanf("%s",str_name);
strcpy(v.name,str_name);
printf("\n");
printf(" 请输入景点介绍:\n\n");
printf(" ");
scanf("%s",str_features);
strcpy(v.features,str_features);
printf("\n");
printf(" 请输入新增景点的边数:\n\n");
printf(" ");
scanf("%d",&edge);
printf("\n");
printf(" 请输入与新增景点连通的景点编号以及路径长度:\n\n");
G->e+=edge;
G->n=G->n+1;
G->vexs[G->n-1]=v;
for(i=0; i<G->n; i++)
G->edges[G->n-1][i]=G->edges[i][G->n-1]=9999;//初始化
for(i=0; i<edge; i++)
{
printf(" ");
scanf("%d %d",&a1[i],&b);//编号和长度
a[i]=ergodic(G,a1[i]);
G->edges[G->n-1][a[i]]=G->edges[a[i]][G->n-1]=b;
printf("\n");
}
}
//删除景点,删除路
//判断是否有该点
void DeleteVertex(Graph *G, int h)
{
int a,b=0,i;
if(h==-1)
{
printf(" 无此景点\n\n\n\n\n");
Sleep(1000);
}
else
{
strcpy(G->vexs[h].features,"");
strcpy(G->vexs[h].name,"");
for(i=0; i<G->n; i++)
{
if(G->edges[h][i]!=INF||G->edges[h][i]!=0)
{
G->edges[h][i]=G->edges[i][h]=INF;
b++;
}
}
}
}
//增加道路
void InsertArc(Graph *G,int v, int w)
{
int length;
printf(" 请输入新加道路的长度:\n\n");
printf(" ");
scanf("%d",&length);
int a=ergodic(G,v);
int b=ergodic(G,w);
G->edges[a][b]=G->edges[b][a]=length;
}
//删除道路
void DeleteArc(Graph*G,int v,int w)
{
int a=ergodic(G,v);
int b=ergodic(G,w);
if(a==-1||b==-1)
{
printf(" 无此景点\n\n\n\n\n");
Sleep(1000);
}
else
G->edges[a][b]=G->edges[b][a]=9999;
}
void floyd(Graph *G,int path[][20],int dist[][20])
{
int start,end;
int i,j,k;
int tmp;
printf("请输入你所在位置的编号:");
scanf("%d",&start);
printf("请输入你要去位置的编号:");
scanf("%d",&end);
for(i=0;i<G->n;i++)
{
for(j=0;j<G->n;j++)
{
dist[i][j]=G->edges[i][j];
path[i][j]=j;
}
}
for(k=0;k<G->e;k++)
{
for(i=0;i<G->e;i++)
{
for(j=0;j<G->e;j++)
{
tmp=(dist[i][k]==INF||dist[k][j]==INF)?INF:(dist[i][k]+dist[k][j]);
if(dist[i][j]>tmp)
{
dist[i][j]=tmp;
path[i][j]=k;
}
}
}
}
printf("\n ★★★%s--->%s的最短路径长度为: %2d",G->vexs[start].name,G->vexs[end].name,dist[start][end]);
printf("\n 路径为:%s",G->vexs[end].name);
if(path[start][end]==end) printf("->%s\n",G->vexs[start].name);
else{
k=end;
while(path[start][k]!=k)
{
k=path[start][k];
printf("->%s\n",G->vexs[k].name);
}
}
}
//根据地点名确定地点序号
int Locate(Graph *G, char name[])
{
int i;
for(i = 0; i < G->n; i++){
//图中含有该景点,找到其序号
if(!strcmp(G->vexs[i].name, name))
return i;
}
return -1;
}
//查询任意两景点间的最短路径
void Dij_Short_Path(Graph *G)
{
char name[50], choice = 'y'; //
int start, end;
int dist[20+1];
printf("\t\t\t\t\t 最短路径...\n\n\n\n");
while(choice == 'y' || choice == 'Y'){
int path[20+1][20+1] = {0};
printf("\n\t\t\t\t\t请输入起点:");
scanf("%s", name);
start = Locate(G, name);
while(start == -1)
{
printf("\t\t\t\t无效输入,请重新输入:");
scanf("%s", name);
start = Locate(G,name);
}
printf("\t\t\t\t\t请输入终点:");
scanf("%s", name);
end = Locate(G, name);
while(end == -1)
{
printf("\t\t\t\t无效输入,请重新输入:");
scanf("%s", name);
end = Locate(G,name);
}
Dijkstra(G, start, end, dist, path);
printf("\t\t\t\t\t是否继续查询(y || n):");
getchar();
choice = getchar();
}
}
//采用Dijkstra算法求单元点的最短路径
void Dijkstra(Graph *G, int start, int end, int dist[], int path[][20+1])
{
int mindist, i, j, k, t = 1;
//初始化
for(i = 1; i <= G->n; i++){
dist[i] = G->edges[start][i]; //读入开始行的邻接信息
if(G->edges[start][i] != INF)
path[i][1] = start;
}
path[start][0] = 1;
//寻求最短路径
for(i = 2; i <= G->n; i++){
mindist = INF;
for(j = 1; j <= G->n; j++){
if(!path[j][0] && dist[j] < mindist){
mindist = dist[j];
k = j;
}
}
if(mindist == INF) break;
path[k][0] = 1;
//修改加入后的最短路径
for(j = 1; j <= G->n; j++){
if(!path[j][0] && G->edges[k][j] < INF && G->edges[k][j] + dist[k] < dist[j]){
dist[j] = dist[k] + G->edges[k][j];
//记录最短路径
t = 1;
while(path[k][t]){
path[j][t] = path[k][t];
t++;
}
path[j][t] = k;
path[j][t+1] = 0;
}
}
}
if(dist[end] == INF){
printf("\n\n\t%s----->%s 不存在通路!!!\n", G->vexs[start].name, G->vexs[end].name);
return;
}
//输出最短路径
printf("\n\n\t%s----->%s", G->vexs[start].name, G->vexs[end].name);
printf("\n\t距离为:%dm\n", dist[end]);
}
void Floyd(Graph *G)
{
int v,u,i,w,k,j,flag=1,p[20][20][20],D[20][20];
for(v=0;v<G->n;v++)
for(w=0;w<G->n;w++)
{
D[v][w]=G->edges[v][w];
for(u=0;u<G->n;u++)
p[v][w][u]=0;
if(D[v][w]<INF)
{
p[v][w][v]=1;
p[v][w][w]=1;
}
}
for(u=0;u<G->n;u++)//中转点
for(v=0;v<G->n;v++)//源点
for(w=0;w<G->n;w++)//终点
if(D[v][u]+D[u][w]<D[v][w])//不满足三角不等式就更新距离
{
D[v][w]=D[v][u]+D[u][w];
for(i=0;i<G->n;i++)
p[v][w][i]=p[v][u][i]||p[u][w][i];
}
while(flag)
{
printf("请输入出发点和目的地的编号:");
scanf("%d %d",&k,&j);
if(k<0||k>G->n||j<0||j>G->n)//判断输入是否合法
{
printf("景点编号不存在!请重新输入出发点和目的地的编号:");
scanf("%d %d",&k,&j);
}
if(k>=0&&k<G->n&&j>=0&&j<G->n)
flag=0;
}
printf("%s",G->vexs[k].name);
for(u=0;u<G->n;u++)
if(p[k][j][u]&&k!=u&&j!=u)
printf(" *** %s",G->vexs[u].name);//输出到某个点的最短路径
printf(" *** %s",G->vexs[j].name);
printf(" 总路线长%dm\n",D[k][j]);
}
int show()
{
printf(" 管理员页面 \n");
printf(" 1.景点介绍 \n\n");
printf(" 2.修改景点信息 \n\n");
printf(" 3.增加景点 \n\n");
printf(" 4.删除景点 \n\n");
printf(" 5.增加道路 \n\n");
printf(" 6.删除道路 \n\n");
printf(" 7.查找任意两个景点的最短路径 \n\n");
printf(" 8.查看校园路径 \n\n");
printf(" 9.查看校园导航仿真图 \n\n");
printf(" 10.退出导航 \n\n");
printf("请选择相应的功能: ");
int data;
scanf("%d",&data);
return data;
}
int show_1()
{
printf(" 游客页面 \n");
printf(" 1.景点介绍 \n\n");
printf(" 2.查找任意两个景点的最短路径 \n\n");
printf(" 3.查看校园导航仿真图 \n\n");
printf(" 4.退出导航 \n\n");
printf("请选择相应的功能: ");
int data;
scanf("%d",&data);
return data;
}
void show0(Graph *G)
{
int i;
for(i=0;i<G->n;i++)
{
printf(" %d->%s\n",i,G->vexs[i].name);
}
}
void show3()
{
printf("体检中心(0)------------操场(4)------校门北口(8)-----银杏景观(10)\n");
printf(" \\ / \\ \\ /\n");
printf(" \\ / \\ \\ /\n");
printf(" \\ / 图书馆(5) \\ /\n");
printf(" \\ /______/ | \\ \\ /\n");
printf(" 邯郸音乐厅(1) | \\ 餐厅(11) \n");
printf(" | \\ | \\_______ /\n");
printf(" | \\ 花园景观(6)----------校门东口(9)\n");
printf(" | \\ / | /\n");
printf(" | 信息学部(3) | /\n");
printf(" | \\ | /\n");
printf(" | \\ | /\n");
printf(" | \\ | /\n");
printf(" 网计学院(2) \\ | /\n");
printf(" \\ \\ | /\n");
printf(" \\ \\ | /\n");
printf(" \\__________ \\ | ____/\n");
printf(" 校门南口(7)\n");
printf("\n\n");
}
int main()
{
Graph G;
create(&G);
int a;
int i;
printf("河北大学欢迎您!\n");
printf(" 所有人请注意!\n");
printf(" 后续操作如需输入编号,请记清下面各地点编号!\n");
show0(&G);
printf("欢迎使用本次导航系统,祝您愉快!\n");
printf("请输入您的账号:(管理员为111,游客为222)\n");
int v,w;
scanf("%d",&a);
if(a==111)
{
int data;
while(1)
{
data=show();
printf("\n");
if(data==1)
{
printf(" 请输入要查询的景点编号: ");
int v;
scanf("%d",&v);
Vertex a=GetVex(&G,v);
printf("**************");
printf("%s\n\n\n\n",a.features);
}
else if(data==2)
{
//display(&G);
int nold;
printf(" 请输入要修改信息的景点编号: ");
scanf("%d",&nold);
system("cls");
PutVertex(&G,nold);
}
else if(data==3)
{
Vertex d;
InsertVertex(&G,d);
printf("\n\n\n\n");
printf(" 景点添加成功\n\n\n\n");
}
else if(data==4)
{
int h;
printf(" 请输入要删除景点序号:\n\n");
printf(" ");
scanf("%d",&h);
DeleteVertex(&G,h);
printf("\n\n\n\n");
printf(" 景点删除成功\n\n\n\n");
}
else if(data==5)
{
int v,w;
printf(" 请输入与新增路连接的两个景点编号:\n\n");
printf(" ");
scanf("%d %d",&v,&w);
InsertArc(&G,v,w);
printf("\n\n\n\n");
printf(" 道路添加成功\n\n\n\n");
}
else if(data==6)
{
int v1,w1;
printf(" 请输入与要删除路连接的两个景点编号:\n\n");
printf(" ");
scanf("%d %d",&v1,&w1);
DeleteArc(&G,v1,w1);
printf("\n\n\n\n");
printf(" 道路删除成功\n\n\n\n");
}
else if(data==7)
{
system("cls");
Dij_Short_Path(&G);
printf("\n\n");
}
else if(data==8)
{
display(&G);
}
else if(data==9)
{
show3();
}
else if(data==10)
{
//exit(0);
int data;
int dist[20],path[20][20];
while(1)
{
data=show_1();
printf("\n");
if(data==1)
{
printf(" 请输入要查询的景点编号: ");
int v;
scanf("%d",&v);
Vertex a=GetVex(&G,v);
printf("**************");
printf("%s\n\n\n\n",a.features);
}
else if(data==2)
{
system("cls");
Floyd(&G);
printf("\n\n");
}
else if(data==3)
{
show3();
}
else if(data==4)
{
exit(0);
}
}
}
}
}
if(a==222)
{
int data;
int dist[20],path[20][20];
while(1)
{
data=show_1();
printf("\n");
if(data==1)
{
printf(" 请输入要查询的景点编号: ");
int v;
scanf("%d",&v);
Vertex a=GetVex(&G,v);
printf("**************");
printf("%s\n\n\n\n",a.features);
}
else if(data==2)
{
system("cls");
Floyd(&G);
printf("\n\n");
}
else if(data==3)
{
show3();
}
else if(data==4)
{
exit(0);
}
}
}
return 0;
}