#include<iostream> #include<cstdio> #include<cstring> #define MAX 9999999 using namespace std; typedef struct ArcCell{ int length;//两点间的距离 }ArcCell, AdjMatrix[100][100]; //景点 typedef struct { char sce_name[30];//景点名称 int sce_num;//景点代号 char sce_intro[200];//景点简介 }Scenery; //图的数组表示法 typedef struct { Scenery vexs[100]; AdjMatrix arcs; int vexnum,arcnum; }MGraph; //全局变量 int Path[100];//记录最短路径上的节点 int D[100];//记录节点到起始节点的距离 bool final[100];//标记该节点是否在路径上 //由风景名称获取风景在数组中的下标 int GetSce(char sce_name[],MGraph G){ int i; for(i=1;i<=G.vexnum;i++) if(strcmp(sce_name,G.vexs[i].sce_name)==0)return i; return -1; } //创建一个图 void Creat_Graph(MGraph &G){ int i,j; int n1,n2,weight; //起始下标、终止下标、权值 char start[30], end[30]; printf("■请输入景点个数: "); scanf("%d",&G.vexnum);//景点个数 printf("■请输入路的条数: "); scanf("%d",&G.arcnum);//路的条数 printf(" ■输入景点信息(名称(char)、代号(int)、简介(char)). "); for(i=1;i<=G.vexnum;i++){ printf("第 %d 个景点: ",i); scanf("%s",G.vexs[i].sce_name); scanf("%d",&G.vexs[i].sce_num); scanf("%s",G.vexs[i].sce_intro); } printf(" ■输入路况: "); //先把二维数组给填一下 (相当于vexnum阶矩阵) for(i=1;i<=G.vexnum;i++){ for(j=1;j<=G.vexnum;j++){ G.arcs[i][j].length = MAX; } } for(i=1;i<=G.arcnum;i++){ printf("■弧头 & 弧尾 & 权值: "); scanf("%s",start); scanf("%s",end); n1 = GetSce(start,G);//经上面的景点信息获取景点的下标 n2 = GetSce(end,G); scanf("%d",&weight); G.arcs[n1][n2].length = weight;//矩阵双向的权值 G.arcs[n2][n1].length = weight; } printf("OK! 信息录入完毕! "); } //输出最短路径 void OutPutPath(MGraph G,bool find,int sn,int en){ int i; int path[100]; if(!find){ printf("Sorry,无法找到从%s到%s的路. ",G.vexs[sn].sce_name,G.vexs[en].sce_name); return; } else { printf(" ■■■%s 到 %s 最短路径上依次为: ",G.vexs[sn].sce_name,G.vexs[en].sce_name); path[0] = en; int k = 1,x = Path[en]; while(x != sn){ path[k++] = x; x = Path[x]; } path[k] = sn; for(i=k;i>=0;i--){ printf("%s",G.vexs[path[i]].sce_name); if(i!=0){ printf(" → "); } } printf(" ■■■其最短路径长度为: %d ",D[en]); printf(" "); } } //迪杰斯特拉算法求最短路径 void Dijkstra(MGraph G,int sn,int en){ int i; int v, min;//v--点的下标,min--节点离起始的距离 for(i=1; i<=G.vexnum; i++){ final[i] = false;//用于记录是否在已确定的点的集合中 D[i] = G.arcs[sn][i].length;//每个点与起点的距离 //初始化记录最短路径的数组 if(D[i]!= MAX)//与起点相连 Path[i] = sn; else//不与起点相连 Path[i] = 0; } D[sn] = 0;//初始化最开始的距离0 final[sn] = true;//起始节点在路径上 Path[sn] = sn;//记录最短路径上的第一个节点 bool find = false;//判断是否找到从起点到终点的路 while(1){ min = MAX; v = -1;//先默认一个不存在的下标,下面根据各步的比较把最近点的下标赋给v for(i = 1; i <= G.vexnum; i++){//找到当前位置与起点最近的点 if(final[i]==false && D[i] < min){//剩下的Ian还没连到最短路径上,而且点和最短路径的节点有通路 v = i; min = D[i]; } } if(v==-1){//如果找不到最近的点,就没有必要求最短路径了,直接输出找不到路 find = false; break; } final[v] = true; for(i=1;i<=G.vexnum;i++){//修改每个点到起点的最近距离 ,若修改了,则说明通过v点修改点离起点更近了,此时记录Path[i] = v; if(final[i]==false && (min + G.arcs[v][i].length <D[i])){ D[i] = min + G.arcs[v][i].length; Path[i] = v;//这样就把下一个最近的点连接到路径上了 } } if(v == en){//到达尾节点,结束循环 find = true; break; } } OutPutPath(G,find,sn,en);//输出最短路径 } int main(){ while(1){ MGraph G; char start[30],end[30],name[30],num;//起点集、终点集、名称集、景点对应的下标 int sn,en,choice;//起始点、终止点 printf(" ■校园景点游览■ "); Creat_Graph(G);//创建图 while(1){ printf("■用户操作: "); printf("(1)景点信息 (2)最短距离 "); scanf("%d",&choice); if(choice == 1){ printf("■请输入要查找的景点的名称: "); scanf("%s",name); num = GetSce(name, G); printf("名称:%s 代号:%d 简介:%s ",name,G.vexs[num].sce_num,G.vexs[num].sce_intro); }else if(choice == 2){ printf("起点 & 终点:"); scanf("%s",start); scanf("%s",end); sn = GetSce(start,G); en = GetSce(end,G); if(sn==en) printf("您输入的起始位置和终止位置相等,所以不必查询. "); else Dijkstra(G,sn,en);//输出最短路径 } printf("■请输入您的选择: "); printf("■(0)继续查询 (1)退出 "); int q; scanf("%d",&q); if(q){ printf("May the code be with u!"); exit(0); } } } return 0; }