提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
- 代码
- 总结
前言
参考资料【C++期末大作业】数据结构课设 | 智能公交车查询系统_米莱虾的博客-CSDN博客_c++期末大作业
Dijkstra算法详解(完美图解、趣学算法)_wjyGrit的博客-CSDN博客_dijkstra
正文
#include<stdio.h>
#include<string.h>
#include<stdbool.h>
#include<stdlib.h>
#define maxstation 100
#define maxbus 20
#define Inf 65535
char station[maxstation][20];
int stanmb=0; //总站点数
int busnmb=0; //总公交线数
int way[maxbus][maxstation]={{0}}; //记录公交顺序
int versta[maxstation]; //记录公交站对应的图顶点位置
typedef struct
{
char vertex[maxstation][20]; //顶点合集
int arc[maxstation][maxstation]; //边合集且为权值
int vexnum,arcnum; //顶点数和边数
}graph;
typedef struct
{
int busnum; //公交车序号
char stnname[maxstation][20]; //站点名
int stationnum; //站点数量
}busline;
graph g;
busline bus[maxbus];
bool flag[maxstation]; //dijstra预留空间
int dist[maxstation],p[maxstation];
void initG() //图的初始化
{
FILE *fp,*fq;
if((fp=fopen("Vertex.txt","r"))==NULL)
{printf("地点读取错误");
exit(0);
}
if((fq=fopen("graph.txt","r"))==NULL)
{printf("路线读取错误");
exit(0);
}
fscanf(fp,"%d",&g.vexnum); //导入顶点集
for(int i=0;i<g.vexnum;i++)
fscanf(fp,"%s",g.vertex[i]);
for(int i=0;i<g.vexnum;i++)
{
for(int j=0;j<g.vexnum;j++)
g.arc[i][j]=Inf;
}
fscanf(fq,"%d",&g.arcnum); //导入边集
int u,v;
for(int i=0;i<g.arcnum;i++)
{
fscanf(fq,"%d %d",&u,&v);
fscanf(fq,"%d",&g.arc[u][v]);
g.arc[v][u]=g.arc[u][v];
}
}
void exchange() //将公交站在公交线的顺序记录在表中 ,并且表示公交站与公交线的关系
{
int k;
for(int i=0;i<busnmb;i++)
{
for(k=0;k<bus[i].stationnum;k++)
for(int j=0;j<maxstation;j++)
if(strcmp(bus[i].stnname[k],station[j])==0)
way[i][j]=k+1;
}
for(int i=0;i<stanmb;i++) //将公交站在图顶点集中的位置记录下来
{
for(int j=0;j<g.vexnum;j++)
if(strcmp(station[i],g.vertex[j])==0)
{
versta[i]=j;
}
}
}
void init() //初始化 //初始化
{
FILE *fp,*fq;
if((fp=fopen("Station.txt","r"))==NULL)
{printf("站点读取错误");
exit(0);
}
if((fq=fopen("busline.txt","r"))==NULL)
{printf("公交线读取错误");
exit(0);
}
fscanf(fp,"%d",&stanmb); //导入公交站集合
for(int i=0;i<stanmb;i++)
fscanf(fp,"%s",station[i]);
for(int i=0;i<maxbus;i++) //导入公交线信息
{
fscanf(fq,"%d %d",&bus[i].busnum,&bus[i].stationnum);
if(bus[i].busnum!=0)
{
busnmb++;
for(int j=0;j<bus[i].stationnum;j++)
{
fscanf(fq,"%s",bus[i].stnname[j]);
}
}
else break;
}
initG();
exchange();
}
void Printbusline(int n) //输出某条公交线所有的站点
{
printf("%d号线站点为:",bus[n].busnum);
for(int i=0;i<bus[n].stationnum;i++)
printf("%5s ",bus[n].stnname[i]);
printf("\n\n");
}
void PrintAllbusline() //输出所有公交线的站点
{
for(int i=0;i<busnmb;i++)
{
if(bus[i].busnum!=0)
{
Printbusline(i);
printf("\n");
}
}
}
void stationsearch() //查找站点所属的公交线并输出
{
char n[20];
printf("\n请输入当前站点:\n");
scanf("%s",n);
int i,j;
for(i=0;i<stanmb;i++)
if(strcmp(n,station[i])==0)
break;
int ret=0;
for(j=0;j<busnmb;j++){
if(way[j][i]>0)
{
printf("该站点属于%d号线\n",bus[j].busnum);
Printbusline(j);
}
else ret++;
}
if(ret==busnmb) printf("该站点不属于任何公交线");
}
void change(int a,int b) //换乘
{
int u,v; //找到两个站点分别属于哪条公交线
for(int i=0;i<busnmb;i++)
{
if(way[i][a]>0)
u=i;
if(way[i][b]>0)
v=i;
}
int t;
int i;
for(i=0;i<stanmb;i++) //找到换乘站点
if(way[u][i]>0&&way[v][i]>0)
{
t=way[u][i]-way[u][a]+way[v][i]-way[v][b];
break;}
printf("\n在%s乘坐%d号线到达%s后,\n换乘%d号线到达%s耗时约为%d分钟\n",station[a],bus[u].busnum,station[i],bus[v].busnum,station[b],(t));
}
void Link(char m[20],char n[20]) //直达
{
int a,b;
for (int i=0;i<stanmb;i++)
{
if(strcmp(station[i],m)==0)
a=i;
if(strcmp(station[i],n)==0)
b=i;
}
int ret=0;
for (int i=0;i<busnmb;i++)
{
if(way[i][a]>0&&way[i][b]>0)
{
int t=way[i][a]-way[i][b];
printf("\n%s到%s有直达线%d号线,耗时约为%d分钟\n",m,n,bus[i].busnum,abs(t));
ret++;
}
}
if(ret==0) change(a,b);
}
void dijstra(int u) //dijstra 算法
{
int n=g.vexnum;
for(int i=0;i<n;i++)
{
dist[i]=g.arc[u][i];
flag[i]=false;
if(dist[i]==Inf)
p[i]=-1;
else
p[i]=u;
}
flag[u]=true;
dist[u]=0;
for(int i=0;i<n;i++){
int temp=Inf,t=u;
for(int j=0;j<n;j++){
if(!flag[j]&&dist[j]<temp){
t=j;
temp=dist[j];
}
}
if(t==u) return;
flag[t]=true;
for(int j=0;j<n;j++){
if(!flag[j]&&g.arc[t][j]<Inf){
if(dist[j]>(dist[t]+g.arc[t][j]))
{
dist[j]=dist[t]+g.arc[t][j];
p[j]=t;
}
}
}
}
}
void walk() //步行距离查询
{
char m[20],n[20];
printf("\n请输入起点:");
scanf("%s",m);
printf("\n请输入终点:");
scanf("%s",n);
int a,b;
for (int i=0;i<stanmb;i++)
{
if(strcmp(g.vertex[i],m)==0)
a=i;
if(strcmp(g.vertex[i],n)==0)
b=i;
}
dijstra(a);
printf("\n%s到%s的步行最短距离大约是%d米\n",m,n,dist[b]);
}
int nearsta(int a)
{
dijstra(a);
int near,less=999;
for (int i=0;i<stanmb;i++)
{
if(less>dist[versta[i]])
{
near=versta[i];
less=dist[versta[i]];
}
}
printf("\n%s最近的站点是%s,步行距离为%d,所需时间为%d分钟\n",g.vertex[a],g.vertex[near],less,(less/50));
return near;
}
void Mtplan()
{
char start[20],end[20];
int s,e; // 记录起点终点对应的值
int n1,n2; //记录最近站点对应的值
char m[20],n[20]; //记录最近的站点名字
printf("\n请输入起点站: ");
scanf("%s",start);
for(int i=0;i<g.vexnum;i++)
{
if(strcmp(start,g.vertex[i])==0)
s=i;
}
printf("\n请输入终点站: ");
scanf("%s",end);
for(int i=0;i<g.vexnum;i++)
{
if(strcmp(end,g.vertex[i])==0)
e=i;
}
n1=nearsta(s);
n2=nearsta(e);
for(int i=0;i<stanmb;i++)
{
if(strcmp(g.vertex[n1],station[i])==0)
{strcpy(m,station[i]);}
if(strcmp(g.vertex[n2],station[i])==0)
{strcpy(n,station[i]);}
}
Link(m,n);
}
void Wks()
{
int i,n;
for(i=0;i<g.vexnum;i++)
{
if(strcmp("五棵松",g.vertex[i])==0)
{n=i;
break;
}
}
dijstra(n);
int x;
for(i=0;i<g.vexnum;i++)
{
x=p[i];
printf("%s->",g.vertex[i]);
for(int j=0;j<g.vexnum;j++)
{
printf("%s->",g.vertex[x]);
x=p[x];
if(x==p[x])break;
}
printf("五棵松\n五棵松到%s的距离是%d\n\n\n",g.vertex[i],dist[i]);
}
}
void writebusline() //重新写入公交线文件
{
FILE *fp;
fp=fopen("busline.txt","w");
for(int i=0;i<busnmb;i++)
{
fprintf(fp,"%d %d\n",bus[i].busnum,bus[i].stationnum);
for(int j=0;j<bus[i].stationnum;j++)
{
fprintf(fp,"%s\n",bus[i].stnname[j]);
}
}
}
void writestation() //重新写入公交站文件
{
FILE *fp;
fp=fopen("Station.txt","w");
fprintf(fp,"%d\n",stanmb);
for(int i=0;i<stanmb;i++)
{
fprintf(fp,"%s\n",station[i]);
}
}
void newarc(char a[20],char b[20]){
int m,n;
for(int i=0;i<g.vexnum;i++)
{
if(strcmp(a,g.vertex[i])==0)
m=i;
if(strcmp(b,g.vertex[i])==0)
n=i;
}
if(g.arc[m][n]==Inf)
{printf("请输入两个站点之间的距离:");
scanf("%d",&g.arc[m][n]);
FILE *fp;
fp=fopen("graph.txt","a");
fprintf(fp,"%d\n",g.arc[m][n]) ;
}
else
{
printf("两站点距离信息已有");
}
}
void Newbusline() //新增公交线
{
int n=busnmb;
bus[n].busnum=n+1;
printf("\n新建公交线将为%d号线\n",bus[n].busnum);
printf("请输入新建公交线信息\n");
printf("\n站点数:");
scanf("%d",&bus[n].stationnum);
for(int i=0;i<bus[n].stationnum;i++)
{
if(i==0)
printf("请输入首发站: ");
else
printf("请输入下一站: ");
scanf("%s",bus[n].stnname[i]);
{
newarc(bus[n].stnname[i],bus[n].stnname[i-1]);
}
}
FILE *fp;
fp=fopen("busline.txt","a");
fprintf(fp,"%d %d\n",bus[n].busnum,bus[n].stationnum);
for(int i=0;i<bus[n].stationnum;i++)
{
fprintf(fp,"%s\n",bus[n].stnname[i]);
}
busnmb++;
}
void modibusline() //修改公交线的站点
{
int n,m;
char u[20],v[20];
printf("输入想要修改的公交线:\n");
scanf("%d",&n);
Printbusline(--n);
printf("请输入需要修改的站点:\n");
scanf("%s",u);
for(int i=0;i<bus[n].stationnum;i++) //找到要修改的站点
if(strcmp(bus[n].stnname[i],u)==0)
m=i;
printf("请输入修改后的站点名:\n");
scanf("%s",v);
strcpy(bus[n].stnname[m],v);
Printbusline(n);
}
void deleteStation() //删除公交站点
{
char n[20];
int k[20]={0};
printf("输入要删除的站点:");
scanf("%s",n);
for(int i=0;i<stanmb;i++) //将公交站在站点合集中覆盖
{
if(strcmp(station[i],n)==0)
{
for(int j=i;j<stanmb-1;j++)
{
strcpy(station[j],station[j+1]);
}
stanmb--;
break;
}
}
for(int i=0;i<busnmb;i++) //找到该站点原本属于的公交线,并将其从中删除
for(int j=0;j<bus[i].stationnum;j++)
{
if(strcmp(bus[i].stnname[j],n)==0)
k[i]=j;
}
for(int i=0;i<busnmb;i++)
{
if(k[i]>0)
{
for(int j=k[i];j<bus[i].stationnum-1;j++)
{
strcpy(bus[i].stnname[j],bus[i].stnname[j+1]);
}
printf("已将%s从%d号线中删除",n,bus[i].busnum);
}
bus[i].stationnum--;
}
}
void AddStation()
{
int u,v=0,w; //u记录新增站点所在公交线,v记录该站点是否属于原来的站点合集
printf("请输入新增站点所属的公交线");
scanf("%d",&u);
u--;
Printbusline(u);
char n[20],m[20];
printf("请输入需要增加的站点名:\n");
scanf("%s",n);
printf("请输入它的前一站站点名:\n");
scanf("%s",m);
for(int i=0;i<stanmb;i++) //如果是不属于原来的站点合集,则将新站点加入站点合集
if(strcmp(station[i],n)==0)
{v=1;break;}
if(v==0){
FILE *fp;
fp=fopen("Station.txt","a");
fprintf(fp,"%s\n",n);
strcpy(station[stanmb],n);
stanmb++;
}
for(int i=0;i<bus[u].stationnum;i++) //将原有站点向后移动一格,新站点添加到前一站之后
{
if(strcmp(bus[u].stnname[i],m)==0)
w=i;
}
w++;
for(int j=bus[u].stationnum;j>w;j--)
{
strcpy(bus[u].stnname[j],bus[u].stnname[j-1]) ;
}
strcpy(bus[u].stnname[w],n);
bus[u].stationnum++;
}
void menu1()
{
int select1=0,select2=1;
printf("******************管理端***********************\n");
printf("* 1.新增公交线 *\n");
printf("* 2.修改公交线 *\n");
printf("* 3.删除站点 *\n");
printf("* 4.增加站点 *\n");
printf("* 9.退出 *\n");
printf("***********************************************\n");
scanf("%d",&select1);
switch(select1)
{
case 1:
while(select2)
{
Newbusline();
init();
printf("\n是否继续?\n1.继续 0.退出\n");
scanf("%d",&select2);
}
break;
case 2:
while(select2)
{
modibusline();
writebusline();
init();
printf("\n是否继续?\n1.继续 0.退出\n");
scanf("%d",&select2);
}
break;
case 3:
while(select2)
{
deleteStation();
writestation();
writebusline();
init();
printf("\n是否继续?\n1.继续 0.退出\n");
scanf("%d",&select2);
}break;
case 4:
while(select2)
{
AddStation();
writebusline();
init();
printf("\n是否继续?\n1.继续 0.退出\n");
scanf("%d",&select2);
}
break;
}
if(select1>0&&select1<9)
menu1();
}
void menu0()
{
int select1,select2=1;
printf("******************学生端***********************\n");
printf("* 1.查询站点公交信息 *\n");
printf("* 2.查询所有公交路线信息 *\n");
printf("* 3.公交站点换乘规划 *\n");
printf("* 4.步行路程最短距离 *\n");
printf("* 5.步行和公交最少耗时规划 *\n");
printf("* 6.五棵松到所有站点路程 *\n");
printf("* 9.退出 *\n");
printf("***********************************************\n");
scanf("%d",&select1);
switch(select1)
{
case 1:
while(select2)
{
stationsearch();
printf("\n是否继续?\n1.继续 0.退出\n");
scanf("%d",&select2);
}
break;
case 2:
while(select2)
{
PrintAllbusline();
printf("\n是否继续?\n1.继续 0.退出\n");
scanf("%d",&select2);
}
break;
case 3:
while(select2)
{ char m[20],n[20];
printf("\n请输入起点:");
scanf("%s",m);
printf("\n请输入终点:");
scanf("%s",n);
Link(m,n);
printf("\n是否继续?\n1.继续 0.退出\n");
scanf("%d",&select2);
}
break;
case 4:
while(select2)
{
walk();
printf("\n是否继续?\n1.继续 0.退出\n");
scanf("%d",&select2);
}
break;
case 5:
while(select2)
{
Mtplan();
printf("\n是否继续?\n1.继续 0.退出\n");
scanf("%d",&select2);
}
break;
case 6:
while(select2)
{
Wks();
printf("\n是否继续?\n1.继续 0.退出\n");
scanf("%d",&select2);
}
break;
}
if(select1>0&&select1<9)
menu0();
else if(select1==666)
menu1();
}
int main()
{
init();
menu0();
return 0;
}