//校园导游咨询系统
#include<stdio.h>
#include<malloc.h>
#define MAX 30 //顶点最大个数
#define NUM_N 20 //景点名字(英文)的最多字数
#define NUM_I 100//景点简介(英文)的最多字数
#define TRUE 1
#define FALSE 0
#define INFINITY 1000
typedef enum{DG,DN,UDG,UDN} Graphkind; //图的类型
typedef struct arccell //定义表示弧的邻接矩阵
{
int adj;
int *info; //弧的相关信息
}arccell,adjmatrix[MAX][MAX];
typedef struct
{
int symbol; //存放景点代码
char *name; //存放景点名字
char *introduction;//存放景点简介
}node;
typedef struct //定义一个图类型
{
node vexs[MAX]; //图的顶点信息
adjmatrix arcs; //图邻接矩阵
int vexnum,arcnum; //图中点和边的个数
Graphkind kind; //图的种类
}mgraph;
typedef int pathmatrix_DJIK[MAX][MAX];//存放从一点到各点的路径
typedef int shortpathtable[MAX]; //存放从一点到各点的最短路径长度
pathmatrix_DJIK p1;
shortpathtable d1;
///
typedef int pathmatrix_FLOYD[MAX][MAX][MAX];//存放任意两点的路径
typedef int distancmatrix[MAX][MAX];//存放任意两点最短路径的长度
pathmatrix_FLOYD p2;
distancmatrix d2;
///
void main()
{
//变量定义
mgraph g;
///
//函数声明
int locatevex(mgraph g,int v);
int createUDN(mgraph &G);
void shortpath_DJIK(mgraph G,int k,pathmatrix_DJIK &P,shortpathtable &D);
void print_DJIK(mgraph G,pathmatrix_DJIK P,shortpathtable D);
void shortpath_FLOYD(mgraph G,pathmatrix_FLOYD &P,distancmatrix &D);
void print_FLOYD(mgraph G,pathmatrix_FLOYD P,distancmatrix D);
void search(mgraph G);
void ctrl(mgraph G);
///
createUDN(g);//调用构造图的函数
while(1)
{ctrl(g);}//重复调用流程控制函数
}
//找出值为v的顶点在图的存储数组中的索引
int locatevex(mgraph g,int v)
{
for(int i=0;i<g.vexnum;++i)
if(g.vexs[i].symbol==v)return i;
}
//此函数计划从文件读取数据
int createUDN(mgraph &G) //构造无向网
{
int i,j,k,h;
int v1,v2,w;
G.vexnum=6;
G.arcnum=8;
//图中顶点数据录入
for(h=0;h<G.vexnum;++h)
{
G.vexs[h].name=(char *)malloc(NUM_N*sizeof(char));
G.vexs[h].introduction=(char *)malloc(NUM_I*sizeof(char));
}
G.vexs[0].symbol=1;
G.vexs[0].name="北门";
G.vexs[0].introduction="这是我校的北大门,具有悠久的历史.";
G.vexs[1].symbol=2;
G.vexs[1].name="八教";
G.vexs[1].introduction="这是学校的第八教学楼,其中教学设施配备齐全.为同学们创造了良好的学习条件.";
G.vexs[2].symbol=3;
G.vexs[2].name="桔园";
G.vexs[2].introduction="这是个学生宿舍园区,这里环境优雅,条件舒适.为同学们创造了良好的生活条件.";
G.vexs[3].symbol=4;
G.vexs[3].name="田家炳";
G.vexs[3].introduction="这是学校的行政管理中心.";
G.vexs[4].symbol=5;
G.vexs[4].name="图书馆";
G.vexs[4].introduction="这是学校在北校区的图书馆,其中藏书非常丰富";
G.vexs[5].symbol=6;
G.vexs[5].name="第一运动场";
G.vexs[5].introduction="这是学校的第一运动场,设施一流齐全,为同学们创造了良好的娱乐场所.";
/
/
//图中边的数据录入
for(i=0;i<G.vexnum;++i)//初始化邻接矩阵
for(j=0;j<G.vexnum;++j)
{
G.arcs[i][j].adj=INFINITY;
G.arcs[i][j].info=0;
if(i==j)G.arcs[i][j].adj=0;
}
G.arcs[0][1].adj=300;
G.arcs[0][3].adj=300;
G.arcs[0][5].adj=150;
G.arcs[1][3].adj=100;
G.arcs[3][4].adj=70;
G.arcs[3][2].adj=350;
G.arcs[2][4].adj=380;
G.arcs[4][5].adj=100;
for(i=0;i<G.vexnum;++i)
for(j=0;j<G.vexnum;++j)
if(G.arcs[i][j].adj==INFINITY)
G.arcs[i][j].adj=G.arcs[j][i].adj;
/
return 1;
}
//输出菜单选项的函数
void print()
{
printf("**********************MENU************************/n");
printf(" 查询景点信息请输入1;/n");
printf(" 查询到从北大门到各个景点的最短路径请输入2;/n");
printf(" 查询学校任意两个景点信息请输入3;/n");
printf("**************************************************/n");
printf(" 北门:1 八教:2 桔园:3/n");
printf(" 田家炳:4 图书馆:5 第一运动场:6/n");
printf("**************************************************/n");
}
//求从v0到各个顶点的最短路径,用P返回路径,用D返回各路径的总权值
void shortpath_DJIK(mgraph G,int k,pathmatrix_DJIK &P,shortpathtable &D)
{
int v,v0,w,i,j;
int final[MAX]; //用此数组表示某个顶点是否已经并入s集合,其中final[i]表示G中索引为i的顶点
v0=locatevex(G,k);//求数值为k的顶点在G中的索引
for(v=0;v<G.vexnum;++v)
{
final[v]=FALSE; //初始化s集合为空集
D[v]=G.arcs[v0][v].adj; //初始化D[i]为v0到i顶点的权
for(w=0;w<G.vexnum;++w)
P[v][w]=FALSE; //初始化路径
if(D[v]<INFINITY)
{P[v][v0]=TRUE;P[v][v]=TRUE;}
}
D[v0]=0;
final[v0]=TRUE; //初始化,v0顶点属于s集
//开始主循环
for(i=1;i<G.vexnum;++i)
{
int min;
min=INFINITY; //给min赋一个较大的值以便比较
for(w=0;w<G.vexnum;++w)
if(!final[w])
if(D[w]<min){v=w;min=D[w];}//求出距离v0顶点最近的顶点在G中的索引w,并把v0到它的权赋给D[w]
final[v]=TRUE; //将v顶点并入s集合
for(j=0;j<G.vexnum;++j)
if(!final[j]&&(min+G.arcs[v][j].adj<D[j]))
{
D[j]=min+G.arcs[v][j].adj;
for(int h=0;h<G.vexnum;++h)P[j][h]=P[v][h];
P[j][j]=TRUE;
}
}
}
//输出起点到各个顶点的最小长度和经过的顶点的函数
void print_DJIK(mgraph G,pathmatrix_DJIK P,shortpathtable D)
{
int i,j;
for(i=0;i<G.vexnum;++i)
{
if(D[i]==1000)printf("/n从北校门到%s无路径./n",G.vexs[i].name);
else if(D[i]==0);
else
{
printf("/n从北校门到%s的最短路径长度为:%d/n经过的景点有:",G.vexs[i].name,D[i]);
for(j=0;j<G.vexnum;++j)
if(P[i][j]!=0)printf("%s ",G.vexs[j].name);
printf("/n");
}
}
printf("/n");
}
//求任意两个顶点间的最短路径,用P返回路径,用D返回路径的权值
//若P[v][w][u]为TRUE则表明u为v到w的当前最短路径中的点
void shortpath_FLOYD(mgraph G,pathmatrix_FLOYD &P,distancmatrix &D)
{
int v,w,u,i;
for(v=0;v<G.vexnum;++v)
for(w=0;w<G.vexnum;++w)
{
D[v][w]=G.arcs[v][w].adj;//初始化表示各边权值的矩阵
for(u=0;u<G.vexnum;++u)P[v][w][u]=FALSE; //初始化表示路径的矩阵
if(D[v][w]<INFINITY) //从v到w有直接路径
{P[v][w][v]=TRUE;P[v][w][w]=TRUE;} //将v和w在路径矩阵中标示出来
}//for
//开始查找最短路径
for(u=0;u<G.vexnum;++u)
for(v=0;v<G.vexnum;++v)
for(w=0;w<G.vexnum;++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.vexnum;++i)
P[v][w][i]=P[v][u][i] || P[u][w][i];
}//if
}//shortpath_FLOYD
//将两个顶点的最短路径显示出来的函数
void print_FLOYD(mgraph G,pathmatrix_FLOYD P,distancmatrix D)
{
int i,a,b,m,n;
printf("依次输入您要查询的两个景点:/n");
scanf("%d%d",&a,&b);
m=locatevex(G,a);
n=locatevex(G,b);
if(D[m][n]==1000)printf("从%s到%s无路径/n",G.vexs[m].name,G.vexs[n].name);
else
{
printf("从%s到%s的长度为:%d/n经过的景点有:",G.vexs[m].name,G.vexs[n].name,D[m][n]);
for(i=0;i<G.vexnum;++i)
if(P[m][n][i]==TRUE)printf("%s ",G.vexs[i].name);
}
printf("/n");
}
//查询某个景点信息的函数
void search(mgraph G)
{
int n,i;
printf("输入您要查询景点的代码:/n");
scanf("%d",&n);
for(i=0;i<G.vexnum;++i)
if(n==G.vexs[i].symbol)
{printf("景点名称:%s/n景点代码:%d/n景点简介:/n%s/n",G.vexs[i].name,G.vexs[i].symbol,G.vexs[i].introduction);return;}
printf("这里没有您输入的景点代码,请核实./n");
}
//流程控制的函数
void ctrl(mgraph G)
{
int i;
print();
printf("请选择:/n");
scanf("%d",&i);
switch(i)
{
case 1:{search(G);break;}
case 2:{shortpath_DJIK(G,1,p1,d1);print_DJIK(G,p1,d1);break;}
case 3:{shortpath_FLOYD(G,p2,d2);print_FLOYD(G,p2,d2);break;}
}
}