数据结构课程设计大作业——江大公交路线查询系统

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录


前言

参考资料【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;
	
}

总结

  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值