这个应用最难的操作是实现换乘,也就是第5步。对于两个出发站和目的站,有以下几种情况:①直达;②转乘若干次到达;③无法到达。因为只考虑换乘次数最少,并没有考虑走过的距离,以及各站点之间的距离,而且公交车一般都是往返于各站点,那么一条路线上的任意两站点都是双向可通的,所以每一条路线都能构成 一个无向完全图,并且图的边权为1(一个站点可能落在不同的无向完全图中,这样就能实现转乘了)。接下来只需要套用Dijkstra最短路径算法就解决转乘问题了。
未完善代码如下(还有些显示界面没优化到位,基本实现以上5个功能):
#include <stdio.h>
#include <string.h>
#define INT_Max 0x3f3f3f
typedef struct Graph{
int Contact[240][240];
int NA;
int vis[240];
int pv[240];
int Dis[240];
char Matching_name[250][18];
}Graph;Graph G;
typedef struct BUS{
char id[8];
char driver_name[20];
int Fare;
int begin_time,end_time;
int site_amount;
int site[25];
}BUS;
typedef struct Bus_station{
int bus_num;
BUS bus[666];
}Bus_station;Bus_station station;
int Matching_stop_lo(char *stop_name)
{
for(int i=0;i<G.NA;i++)
{
if(strcmp(stop_name,G.Matching_name[i])==0)
return i;
}
return -1;
}
void Query_Bus(char *id)
{
int index = -1;
for(int i=0;i<station.bus_num;i++)
{
if(strcmp(id,station.bus[i].id)==0)
{
index = i;
}
}
printf("%s ",station.bus[index].id);
//其他信息1
//其他信息1
//其他信息1
//其他信息1
}
void Delete_bus(char *id)
{
int index = -1;
for(int i=0;i<station.bus_num;i++)
{
if(strcmp(id,station.bus[i].id)==0)
{
index = i;
}
}
if(index==-1)
return ;
for(int j=index;j+1<station.bus_num;j++)
{
station.bus[j] = station.bus[j+1];
}
station.bus_num--;
}
BUS Creat_Bus_Route()
{
BUS bus;
printf("请输入公交车id:");
scanf("%s",bus.id);
printf("请输入公交车经过的站点数量:");
scanf("%d",&bus.site_amount);
printf("请输入这些站点的名称(以空格分隔,回车结束):");
for(int i=0;i<bus.site_amount;i++)
{
char name[25];scanf("%s",name);
bus.site[i] = Matching_stop_lo(name);
}
printf("已成功创建一条新的线路:");
return bus;
}
/*更新地图*/
void Update_G()
{
for(int i=0;i<G.NA;i++){for(int j=0;j<G.NA;j++)G.Contact[i][j]=INT_Max;}
for(int i=0;i<G.NA;i++){G.Contact[i][i]=0;G.vis[i]=0;G.pv[i]=i;}
for(int i=0;i<station.bus_num;i++){
for(int j=0;j<station.bus[i].site_amount;j++){
for(int k=1;k<station.bus[i].site_amount;k++){
G.Contact[station.bus[i].site[j]][station.bus[i].site[k]]=1;
G.Contact[station.bus[i].site[k]][station.bus[i].site[j]]=1;
}
}
}
}
int Judge_direct(int Starting,int Destination)
{
if(G.Contact[Starting][Destination]==1)
{
for(int i=0;i<station.bus_num;i++)
{
int flag1=0,flag2=0;
for(int j=0;j<station.bus[i].site_amount;j++)
{
if(station.bus[i].site[j]==Starting)
flag1=1;
if(station.bus[i].site[j]==Destination)
flag2=1;
}
if(flag1&&flag2)
return i;
}
}
return -1;
}
void Dijkstra(int Starting,int Destination)
{
int n,v,i,w,Min,p;
n = G.NA;
for(v=0;v<n;v++)
{
G.vis[v]=0;
G.Dis[v]=G.Contact[Starting][v];
if(G.Dis[v]<INT_Max)G.pv[v]=Starting;
else G.pv[v]=v;
}
G.vis[Starting]=1;G.Dis[Starting]=0;
for(i=1;i<n;i++)
{
Min = INT_Max;
for(w=0;w<n;w++)
{
if(!G.vis[w]&&G.Dis[w]<Min)
{
v=w;Min = G.Dis[w];
}
}
G.vis[v]=1;
for(w=0;w<n;w++)
{
if(!G.vis[w]&&(G.Dis[v]+G.Contact[v][w]<G.Dis[w]))
{
G.Dis[w]=G.Dis[v]+G.Contact[v][w];
G.pv[w]=v;
}
}
}
printf("%d\n",G.Dis[Destination]);
int a[123],index=0;
if(G.Dis[w]<INT_Max)
{
p = Destination;
while(p!=G.pv[p])
{
a[index++] = p;
//printf("%d ",p);
p=G.pv[p];
}
//printf("%d ",p);
a[index++] = p;
}
for(i=index-1;i>0;i--)
{
printf("从%s乘坐%s路车到%s\n",G.Matching_name[a[i]],station.bus[Judge_direct(a[i],a[i-1])].id,G.Matching_name[a[i-1]]);
}
printf("按上述路线即可到达目的地\n");
}
void MainMenu()
{
printf("\n\n\n\n ------------欢迎进入乘车系统管理页面,请选择要执行的操作------------\n\n\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(" 0 退出管理系统\n\n");
int op;scanf("%d",&op);
if(op==1)
{
printf("请输入公交路线条数:");
scanf("%d",&station.bus_num);
for(int i=0;i<station.bus_num;i++){station.bus[i] = Creat_Bus_Route();}
Update_G();
}
if(op==2)
{
char id[25];
scanf("%s",id);
Query_Bus(id);
}
if(op==3)
{
char id[25];
scanf("%s",id);
Delete_bus(id);
Update_G();
}
if(op==4)
{
char name1[25],name2[25];
printf("请分别输入出发站和目的站(以空格分隔,回车结束):");
scanf("%s%s",name1,name2);
int l1,l2;
l1 = Matching_stop_lo(name1);
l2 = Matching_stop_lo(name2);
if(Judge_direct(l1,l2)!=-1){
printf("可以直达\n");
}else{
printf("不可直达\n");
}
}
if(op==5)
{
char name1[25],name2[25];
printf("请分别输入出发站和目的站(以空格分隔,回车结束):");
scanf("%s%s",name1,name2);
int l1,l2;
l1 = Matching_stop_lo(name1);
l2 = Matching_stop_lo(name2);
Dijkstra(l1,l2);
}
if(op==6)
{
printf("请输入站点总数:");
scanf("%d",&G.NA);
printf("请输入各站点名称(以空格分隔,回车结束):");
for(int i=0;i<G.NA;i++)
{
scanf("%s",G.Matching_name[i]);
}
Update_G();
}
if(op!=0)
{
MainMenu();
}
}
int main()
{
MainMenu();
return 0;
}