数据结构课程设计4:公交线路提示

1.任务:

[问题描述]

上网下载真实南京公交线路图,建立南京主要公交线路图的存储结构。

[基本要求]

(1)输入任意两站点,给出转车次数最少的乘车路线。

(2)输入任意两站点,给出经过站点最少的乘车路线。

2.采用的数据结构

        使用顺序结构,队列和图

3.算法设计思想

        建立公交车类型结构,对于每辆车的编号,经过的站点数和经过的站点编号进行存储。建立公交站台类型结构,对于每个编号的公交站点的名称,经过该站点的公交车的数量和编号进行存储。

        当寻找经过站点数最少的方案时,使用广度优先遍历,逆向存储,从终点站起,对每个在栈中的站点的公交线路进行遍历,使该线路上该站点的前后站(未进栈过的)依次进栈并标记,记录进栈站点的后一站点和公交线路,直至找到起点站。

        当寻找换乘次数最少的方案时,使用深度优先遍历,逆向存储,从终点起,对每个在栈中的站点的公交线路进行遍历,使该线路上每一个未进栈的站点进栈,并标记其后一站点和公交线路,直至找到起点站为止。

4.源程序

#include <iostream>
#include <string.h>
#include <fstream>
#include <sstream>
#include <string>
#include <windows.h>
using namespace std; 

typedef struct Bus
{
    int No;                         //该公交车的编号
    int StationCount;               //该公交车经过的站点数量
    int BusRoute[80];               //该公交车依次经过的站点编号 
}Bus;

typedef struct Station
{
    char StationName[60];          //站点名称
    int BusCount;                  //经过该站点的公交车数量
    short int bus[35];             //经过该站点的公交车的编号
}Station;

typedef struct BusMap
{
    Bus bus[1000];
    Station station[10000];
    int BusCount;                  //公交车数量
    int StationCount;              //站点数量
}BusMap;

int GetBusStation(BusMap &M, char busname[60])            //获取站台名对应的编号
{
	for (int i=1;i<=M.StationCount;i++)
    {
        if (strcmp(M.station[i].StationName,busname)==0)
        {
        	return i;
        }
    }
    return 0;
}

int IncreaseBusStation(BusMap &M, char busname[60])
{
	int num=GetBusStation(M,busname);
    if (num==0)
    {
        strcpy(M.station[++M.StationCount].StationName,busname);
        num=M.StationCount;
    }
    M.bus[M.BusCount].BusRoute[M.bus[M.BusCount].StationCount]=num;
    M.station[num].bus[++M.station[num].BusCount] = M.bus[M.BusCount].No;
    for (int i=0;i<60; i++)
    {
        busname[i]='\0';
    }
    return num;
}

int CreateMap(BusMap &M)                                  //创建图 
{
	M.BusCount=0;
    M.StationCount=0;
    for (int i=0; i<1000;i++)
    {
        M.bus[i].StationCount=1;
    }
    for (int i=0;i<10000;i++)
    {
        M.station[i].BusCount=0;
    }
    
    int num=0;
    char busname[60];
    char ch;
    FILE *fp;
    if ((fp=fopen("南京公交线路.txt", "r"))==NULL)
    {
        printf("文件打开失败\n");
        exit(0);
    }
    fscanf(fp, "%d", &M.bus[++M.BusCount].No);
    while (ch!=' ')
    {
    	ch=fgetc(fp);
	}
    while (1)
    {
        ch=fgetc(fp);
        if (feof(fp))
        {
            IncreaseBusStation(M,busname);
            break;
        }
        if(ch==' ')
        {
            continue;
		}
        if(ch==',')
        {
            IncreaseBusStation(M,busname);
            num=0;
            M.bus[M.BusCount].StationCount++;
            continue;
        }
        if(ch=='\n')
        {
            IncreaseBusStation(M,busname);
            num=0;
            char chh;
            chh=fgetc(fp);
            if (feof(fp))
            {
            	break;
			}
            fseek(fp, -1L, 1);
            fscanf(fp, "%d", &M.bus[++M.BusCount].No);
            while (ch != ' ')
            {
            	ch = fgetc(fp);
			}
            continue;
        }
        busname[num++]=ch;
    }
    fclose(fp);
}

int GetBus(BusMap &M, int No)                             //获取公交线路对应的编号 
{
    for (int i=1; i<= M.BusCount;i++)
    {
        if (M.bus[i].No == No)
        {
        	return i;
		} 
    }
    return 0;
}

typedef struct LNode                                      //队列基本操作 
{
	int data;
	struct LNode *next;
}LNode,*QueuePtr;

typedef struct LinkQueue
{
	QueuePtr front;
	QueuePtr rear;
}LinkQueue;

void InitQueue(LinkQueue &Q)
{
	Q.front=Q.rear=(LNode *)malloc(sizeof(LNode));
	if(Q.front==NULL) exit -1;
	Q.front->next=NULL; 
}

int QueueEmpty(LinkQueue Q)
{
	if (Q.front!=Q.rear)
	{
		return 0;
	}
	else
	{
		return 1;
	}
}

void EnQueue(LinkQueue &Q,int e)
{
	LNode *s;
	s=(LNode *) malloc(sizeof(LNode));
	if(s==NULL) exit -1;
	s->data=e;
	Q.rear->next=s;
	Q.rear=s;
}

int DeQueue(LinkQueue &Q)
{
	LNode *p;
	int e;
	if (Q.front==Q.rear) return -1;
	p=Q.front->next;
	e=p->data;
	Q.front->next=p->next;
	if(Q.rear == p)
	{
		Q.rear=Q.front;
	}
	free(p);
	return e;
}

typedef struct info                           //PreStation记录前一站号,busno记录经过该站所乘坐的公交车 
{
	int NextStation;
	int busno;
	short int visited;
}info;

info k[10000];

int FindLeastStationNum(BusMap &M,char StartStation[60],char EndStation[60])         //寻找乘坐站数最少的方案 
{
	int start,end;
	start=GetBusStation(M,StartStation);
	end=GetBusStation(M,EndStation);
	for(int i=1;i<10000;i++)
	{
		k[i].visited=0;
		k[i].NextStation=i;
		k[i].busno=0;
	}
	
	LinkQueue Q;
	InitQueue(Q);
	EnQueue(Q,end);                          //倒序查找 
	k[end].visited=1;
	int count=1;
	while(1)
	{
		count++; 
		EnQueue(Q,-1);                        //-1为标记 
		while(Q.front!=Q.rear)
		{
			end=DeQueue(Q);
			if(end==-1)
			{
				break;
			}
			for(int i=1;i<=M.station[end].BusCount;i++)                     //遍历所有经过此站的线路 
			{
				int b;
				b=GetBus(M,M.station[end].bus[i]);
				for(int j=1;j<=M.bus[b].StationCount;j++)
				{
					if (M.bus[b].BusRoute[j]==end)                         //找到该路车中该站点的序号 
                    {
                        if (M.bus[b].BusRoute[j+1]==start || M.bus[b].BusRoute[j-1]==start)    //下一站或上一站为起始站 
                        {
                            int bus=k[end].busno;
                            printf("最少经过%d个站点\n\n",count);
                            cout<<M.station[start].StationName;
                            printf("(乘坐%d路)->", M.bus[b].No);
                            count--;
                            while(count--)
                            {
                                if (count==0)
                                {
                                	cout<<M.station[end].StationName<<"(到达终点,下车)"<<endl; 
								}
                                else
                                {
                                	cout<<M.station[end].StationName;
                                	printf("(乘坐%d路)->" ,bus);
								}
                                end=k[end].NextStation;
                                bus=k[end].busno;
                            }
                            return 1;
                        }
 
                        if ((k[M.bus[b].BusRoute[j-1]].visited==0) && (j-1>0) )                       //当前一站存在且未被访问 
                        {
                            k[M.bus[b].BusRoute[j-1]].busno = M.bus[b].No;
                            k[M.bus[b].BusRoute[j-1]].NextStation=end;
                            EnQueue(Q, M.bus[b].BusRoute[j-1]);
                            k[M.bus[b].BusRoute[j-1]].visited=1;
                        }
                        
                        if ((k[M.bus[b].BusRoute[j+1]].visited==0) && (j+1<=M.bus[b].StationCount))    //当后一站存在且未被访问 
                        {
                            k[M.bus[b].BusRoute[j+1]].busno=M.bus[b].No;
                            k[M.bus[b].BusRoute[j+1]].NextStation=end;
                            EnQueue(Q, M.bus[b].BusRoute[j+1]);
                            k[M.bus[b].BusRoute[j+1]].visited=1;
                        }
                        break;
                    }
				}
			}
		}
	}	
}

int FindLeastTransfer(BusMap &M,char StartStation[60],char EndStation[60])         //寻找转车最少的方案
{
	int start,end;
	start=GetBusStation(M,StartStation);
	end=GetBusStation(M,EndStation);
	for(int i=1;i<10000;i++)
	{
		k[i].visited=0;
		k[i].NextStation=i;
		k[i].busno=0;
	}
	
	LinkQueue Q;
	InitQueue(Q);
	EnQueue(Q,end);                          //倒序查找 
	k[end].visited=1;
	int count=1;
	while(1)
	{
		EnQueue(Q,-1);
		while(Q.front!=Q.rear)
		{
			end=DeQueue(Q);
			if(end==-1)
			{
	        	count++;
				break;
			}
			for(int i=1;i<=M.station[end].BusCount;i++)
			{
				int b;
				b=GetBus(M,M.station[end].bus[i]);
				for(int j=1;j<=M.bus[b].StationCount;j++)
				{
					if(M.bus[b].BusRoute[j]==start)
					{
						int bus;
						bus=k[end].busno;
						printf("至少需要乘坐%d班公交车\n",count);
						cout<<M.station[start].StationName;
						printf("(乘坐%d路公交车)->",M.bus[b].No);
						while(count--)
						{
							if(count==0)
							{
								cout<<M.station[end].StationName<<"(到达终点,请下车!)"<<endl;
							}
							else
							{
								cout<<M.station[end].StationName;
								printf("(换乘%d路车)->",bus);
							}
							end=k[end].NextStation;
							bus=k[end].busno;
						}
						return 1;
					}
					else if(k[M.bus[b].BusRoute[j]].visited==0)
					{
						k[M.bus[b].BusRoute[j]].visited=1;
				    	k[M.bus[b].BusRoute[j]].busno=M.bus[b].No;
				    	k[M.bus[b].BusRoute[j]].NextStation=end;
				    	EnQueue(Q,M.bus[b].BusRoute[j]);
					}
				}
			}
		}
	}	
}

int FindLeastTransfer1(BusMap &M,char StartStation[60],char EndStation[60])         //寻找转车最少的方案(具体) 
{
	int start,end;
	start=GetBusStation(M,StartStation);
	end=GetBusStation(M,EndStation);
	int end1=end;
	for(int i=1;i<10000;i++)
	{
		k[i].visited=0;
		k[i].NextStation=i;
		k[i].busno=0;
	}
	LinkQueue Q;
	InitQueue(Q);
	EnQueue(Q,end);                          //倒序查找 
	k[end].visited=1;
	while(1)
	{
		EnQueue(Q,-1);
		while(Q.front!=Q.rear)
		{
			end=DeQueue(Q);
			if(end==-1)
			{
				break;
			}
			for(int i=1;i<=M.station[end].BusCount;i++)
			{
				int b;
				b=GetBus(M,M.station[end].bus[i]);
				
				int loc; 
				for(int j=1;j<=M.bus[b].StationCount;j++)
				{
					if(M.bus[b].BusRoute[j]==end)
					{
						loc=j;
						break;
					}
				}
				
				for(int j=loc+1;j<=M.bus[b].StationCount;j++)
				{
					if(M.bus[b].BusRoute[j]==start)
					{
						int bus;
						bus=k[end].busno;
						printf("具体公交路线如下:\n");
						cout<<M.station[start].StationName;
						printf("(乘坐%d路公交车)->",M.bus[b].No);
						while(end!=end1)
						{
							cout<<M.station[end].StationName;
							printf("(乘坐%d路车)->",bus);
							end=k[end].NextStation;
							bus=k[end].busno;
						}
						cout<<M.station[end].StationName<<"(到达终点,请下车!)"<<endl;
						return 1;
					}
					else if(k[M.bus[b].BusRoute[j]].visited==0)
					{
						k[M.bus[b].BusRoute[j]].visited=1;
				    	k[M.bus[b].BusRoute[j]].busno=M.bus[b].No;
				    	k[M.bus[b].BusRoute[j]].NextStation=M.bus[b].BusRoute[j-1];
				    	EnQueue(Q,M.bus[b].BusRoute[j]);
					}
				}
				
				for(int j=loc-1;j>=1;j--)
				{
					if(M.bus[b].BusRoute[j]==start)
					{
						int bus;
						bus=k[end].busno;
						printf("具体公交路线如下:\n");
						cout<<M.station[start].StationName;
						printf("(乘坐%d路公交车)->",M.bus[b].No);
						while(end!=end1)
						{
							cout<<M.station[end].StationName;
							printf("(乘坐%d路车)->",bus);
							end=k[end].NextStation;
							bus=k[end].busno;
						}
						cout<<M.station[end].StationName<<"(到达终点,请下车!)"<<endl;
						return 1;
					}
					else if(k[M.bus[b].BusRoute[j]].visited==0)
					{
						k[M.bus[b].BusRoute[j]].visited=1;
				    	k[M.bus[b].BusRoute[j]].busno=M.bus[b].No;
				    	k[M.bus[b].BusRoute[j]].NextStation=M.bus[b].BusRoute[j+1];
				    	EnQueue(Q,M.bus[b].BusRoute[j]);
					}
				}
			}
		}
	}	
}

int main() 
{
	BusMap M;
    CreateMap(M);
    char start[60],end[60];
    printf("请输入起点:");
    cin>>start;
    fflush(stdin);
    printf("请输入终点:");
    cin>>end;
    printf("----------------------------------\n\n");
    if(GetBusStation(M,start)==0 || GetBusStation(M,end)==0)
    {
    	printf("站点输入有误!\n");
	}
	else
	{
		FindLeastStationNum(M,start,end);
		printf("\n----------------------------------\n\n");
		FindLeastTransfer(M,start,end);
		printf("\n");
		FindLeastTransfer1(M,start,end);
	}
	return 0;
}

5.源程序测试数据及结果

 公交线路提示测试数据及结果

6.存在问题及解决办法

        在存储车站和公交路线时,使用了数组,无法把握空间,可能会产生大空间的浪费或是溢出的问题。但是由于各个站点经过的公交车数不同,无法使用链表进行存储。可以考虑在之后采用动态存储,例如vector等,不易产生空间问题。

 7.文档内容 

  

     txt文档中每一行表示一个线路,线路号(注意不一定连续,可能有部分数字线路不存在)和后面站名之间用空格分隔,各站名之间用英语逗号分隔。

  (好像没有找到上传文档链接的方法,有需要可以私发邮箱)

  • 7
    点赞
  • 49
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值