公交线路提示

发布时间 2023-12-27 11:03:00作者: 小菜碟子

算法思想:存储图数据,运用广度优先搜索遍历找寻答案。

主要/核心函数分析://寻找经过站点最少的方案 void FindLeastStationNum(BusMap& M, int StartStation, int EndStation)先将终点站点入队,然后出队遍历经过该站点的公交线路并找到该站点对应公交线路的线内ID然后搜索该ID前后没有访问的站点入队,直到找到起点就输出该条路线。运用k巧妙存储线路前后结点信息。//寻找转车最少的方案void FindLeastTransfer(BusMap& M, int StartStation, int EndStation)与前面不同的是,它是遍历该路公交车的所有站点入栈再接着遍历经过它的其他公交线路上的站点,以及如果经过该站点的公交线路上有起点直接输出该线路即可。

  1 #include <iostream>
  2 #include <string.h>
  3 #include <fstream>
  4 #include <sstream>
  5 #include <string>
  6 #include <windows.h>
  7 using namespace std;
  8 //公交线路信息
  9 typedef struct Bus
 10 {
 11     int No;                         //该公交车的编号
 12     int StationCount;               //该公交车经过的站点数量
 13     int BusRoute[70];               //该公交车依次经过的站点的数组下标 
 14 }Bus;
 15 //站点信息
 16 typedef struct Station
 17 {
 18     int StationName;                //站点名称
 19     int BusCount;                   //经过该站点的公交车数量
 20     int bus[34];                   //经过该站点的公交车的编号
 21 }Station;
 22 //大的公交路线图
 23 typedef struct BusMap
 24 {
 25     Bus bus[730];
 26     Station station[6600];
 27     int BusCount;                  //公交车数量
 28     int StationCount;              //站点数量
 29 }BusMap;
 30 //获取站台对应的编号
 31 int GetBusStation(BusMap& M, int ID)            
 32 {
 33     for (int i = 1; i <= M.StationCount; i++)
 34     {
 35         if (M.station[i].StationName==ID)
 36             return i;
 37     }
 38     return 0;
 39 }
 40 //更新图信息
 41 void IncreaseBusStation(BusMap& M, int ID)
 42 {
 43     int num = GetBusStation(M, ID);
 44     //该站台未创建
 45     if (num == 0)
 46     {
 47         //纳入新的station,并将count++
 48         M.station[++M.StationCount].StationName= ID;
 49         num = M.StationCount;//现在ID在站点的编号
 50     }
 51     //给当前公交线加入新的站点,并把该公交线的站点数量++
 52     M.bus[M.BusCount].BusRoute[M.bus[M.BusCount].StationCount++] = num;
 53     //更新该站点经过的公交线路,以及经过公交数量
 54     M.station[num].bus[++M.station[num].BusCount] = M.bus[M.BusCount].No;
 55 }
 56 //创建图 
 57 void CreateMap(BusMap& M)                                 
 58 {
 59     M.BusCount = 0;//公交车数量
 60     M.StationCount = 0;//站点总数
 61     //初始化
 62     for (int i = 0; i < 730; i++)
 63         M.bus[i].StationCount = 1;
 64     for (int i = 0; i < 6600; i++)
 65         M.station[i].BusCount = 0;
 66 
 67     int ID=0;//站点ID
 68     char ch;//一个一个获取字符
 69     FILE* fp;
 70     if ((fp = fopen("all.txt", "r")) == NULL)
 71     {
 72         cout<<"文件打开失败"<<endl;
 73         exit(0);
 74     }
 75     //获取第一个公交车ID
 76     int busid = 0;
 77     ch = fgetc(fp);
 78     while (ch != ' ')
 79     {
 80         busid = busid * 10 + ch - '0';
 81         ch = fgetc(fp);
 82     }
 83     M.bus[++M.BusCount].No=busid;//纳入
 84 
 85     while (1)
 86     {
 87         ch = fgetc(fp);
 88 
 89         if (feof(fp))
 90         {
 91             IncreaseBusStation(M, ID);
 92             break;//文件结束
 93         }
 94         if (ch == ' ')//只找最后的站点ID
 95         {
 96             ID = 0;
 97             continue;
 98         }
 99         if (ch == '\n')
100         {
101             IncreaseBusStation(M, ID);
102             ID = 0;
103             //获取公交ID
104             int busid = 0;
105             ch = fgetc(fp);
106             while (ch != ' ')
107             {
108                 busid = busid * 10 + ch - '0';
109                 ch = fgetc(fp);
110             }
111             //如果和先前的不一样,则开始新的线路创建
112             if (busid != M.bus[M.BusCount].No)
113             {
114                 M.bus[++M.BusCount].No = busid;
115                 continue;
116             }
117             else
118                 continue;
119         }
120         ID = ID * 10 + ch - '0';
121     }
122     fclose(fp);
123 }
124 //获取公交线路对应的编号 
125 int GetBus(BusMap& M, int No)                             
126 {
127     for (int i = 1; i <= M.BusCount; i++)
128     {
129         if (M.bus[i].No == No)
130             return i;
131     }
132     return 0;
133 }
134 //队列内部节点
135 typedef struct LNode
136 {
137     int data;
138     struct LNode* next;
139 }LNode, * QueuePtr;
140 //队列
141 typedef struct LinkQueue
142 {
143     QueuePtr front;
144     QueuePtr rear;
145 }LinkQueue;
146 //队列初始化
147 void InitQueue(LinkQueue& Q)
148 {
149     Q.front = Q.rear = (LNode*)malloc(sizeof(LNode));
150     if (Q.front == NULL) exit(0);
151     Q.front->next = NULL;
152 }
153 //1是空,0是有
154 int QueueEmpty(LinkQueue Q)
155 {
156     if (Q.front != Q.rear)
157         return 0;
158     else
159         return 1;
160 }
161 //队列入队
162 void EnQueue(LinkQueue& Q, int e)
163 {
164     LNode* s;
165     s = (LNode*)malloc(sizeof(LNode));
166     if (s == NULL) exit(0);
167     s->data = e;
168     s->next = NULL;
169     Q.rear->next = s;
170     Q.rear = s;
171 }
172 //队列出队
173 int DeQueue(LinkQueue& Q)
174 {
175     LNode* p;
176     int e;
177     if (Q.front == Q.rear) return -1;//队列为空
178     p = Q.front->next;
179     e = p->data;
180     Q.front->next = p->next;
181     //当前节点为尾节点
182     if (Q.rear == p)
183         Q.rear = Q.front;
184     free(p);
185     return e;
186 }
187 //NextStation记录下一站点,busno记录经过该站所乘坐的公交车 
188 typedef struct info                           
189 {
190     int NextStation;
191     int busno;
192     int visited;
193 }info;
194 
195 info k[6600];//记录行走路线的信息
196 //寻找经过站点最少的方案 
197 void FindLeastStationNum(BusMap& M, int StartStation, int EndStation)         
198 {
199     //记录站点在数组中的下标
200     int start = GetBusStation(M, StartStation);
201     int end = GetBusStation(M, EndStation);
202 
203     //初始化
204     for (int i = 1; i < 6600; i++)
205     {
206         k[i].visited = 0;//标记该结点是否访问过
207         k[i].NextStation = i;
208         k[i].busno = 0;
209     }
210 
211     LinkQueue Q;
212     InitQueue(Q);
213     EnQueue(Q, end);          
214     //倒序查找 
215     k[end].visited = 1;
216 
217     while (Q.front != Q.rear)//队列不为空
218     {
219         end = DeQueue(Q);
220         //遍历所有经过此站的线路 
221         for (int i = 1; i <= M.station[end].BusCount; i++)
222         {
223             //获取该编号公交车对应大Map中bus数组的下标
224             int b = GetBus(M, M.station[end].bus[i]);
225             //遍历该路公交车,找到该站点对应的该公交线路的第几站
226             for (int j = 1; j < M.bus[b].StationCount; j++)
227             {
228                 if (M.bus[b].BusRoute[j] == end)
229                 {
230                     //下一站或上一站为起始站 
231                     if (M.bus[b].BusRoute[j + 1] == start || M.bus[b].BusRoute[j - 1] == start)
232                     {
233                         int count = 0;
234 
235                         int bus = k[end].busno;//start后一个站点的公交
236                         
237                         cout << M.station[start].StationName<<"(乘坐"<<M.bus[b].No<<"路)->";
238                         while (end != GetBusStation(M, EndStation))
239                         {
240                             cout << M.station[end].StationName;
241                             cout << "(乘坐 " << bus << "路)->";
242 
243                             end = k[end].NextStation;
244                             bus = k[end].busno;
245                             count++;
246                         }
247                         cout << M.station[end].StationName << "(到达终点,下车)" << endl;
248                         cout << "最少经过" << count+1 << "个站点" << endl;
249                         return;
250                     }
251                     //当前一站存在且未被访问 
252                     if (j - 1 > 0)
253                     {
254                         if (k[M.bus[b].BusRoute[j - 1]].visited == 0)
255                         {
256                             k[M.bus[b].BusRoute[j - 1]].busno = M.bus[b].No;
257                             k[M.bus[b].BusRoute[j - 1]].NextStation = end;
258                             EnQueue(Q, M.bus[b].BusRoute[j - 1]);
259                             k[M.bus[b].BusRoute[j - 1]].visited = 1;
260                         }
261                     }
262                     //当后一站存在且未被访问 
263                     if (j + 1 < M.bus[b].StationCount)
264                     {
265                         if (k[M.bus[b].BusRoute[j + 1]].visited == 0)
266                         {
267                             k[M.bus[b].BusRoute[j + 1]].busno = M.bus[b].No;
268                             k[M.bus[b].BusRoute[j + 1]].NextStation = end;
269                             EnQueue(Q, M.bus[b].BusRoute[j + 1]);
270                             k[M.bus[b].BusRoute[j + 1]].visited = 1;
271                         }
272                     }
273                     break;//找到第几站就不用继续for了
274                 }
275             }
276         }
277     }
278 }
279 //寻找转车最少的方案
280 void FindLeastTransfer(BusMap& M, int StartStation, int EndStation)        
281 {
282     int start = GetBusStation(M, StartStation);
283     int end = GetBusStation(M, EndStation);
284     for (int i = 1; i < 300; i++)
285     {
286         k[i].visited = 0;
287         k[i].NextStation = i;
288         k[i].busno = 0;
289     }
290 
291     LinkQueue Q;
292     InitQueue(Q);
293     EnQueue(Q, end);                          
294     k[end].visited = 1;
295 
296     //队列不为空
297     while (Q.front != Q.rear)
298     {
299         end = DeQueue(Q);
300         //遍历所有经过该站点的公交车路线
301         for (int i = 1; i <= M.station[end].BusCount; i++)
302         {
303             int b = GetBus(M, M.station[end].bus[i]);
304             //遍历该路公交车的所有站点
305             for (int j = 1; j < M.bus[b].StationCount; j++)
306             {
307                 //如果该路公交车有start结点,就直接走
308                 if (M.bus[b].BusRoute[j] == start)
309                 {
310                     int bus = k[end].busno;
311                     int count = 1;
312                     cout << M.station[start].StationName<<"(乘坐"<< M.bus[b].No <<"路公交车)->";
313                     while (end!= GetBusStation(M, EndStation))
314                     {
315                         
316                         cout << M.station[end].StationName<<"(换乘"<<bus<<"路车)->";
317                         count++;
318                         
319                         end = k[end].NextStation;
320                         bus = k[end].busno;
321                     }
322                     cout << M.station[end].StationName << endl;
323                     cout << "至少需要乘坐" << count << "班公交车" << endl;
324                     return;
325                 }
326                 else if (k[M.bus[b].BusRoute[j]].visited == 0)
327                 {
328                     k[M.bus[b].BusRoute[j]].visited = 1;
329                     k[M.bus[b].BusRoute[j]].busno = M.bus[b].No;
330                     k[M.bus[b].BusRoute[j]].NextStation = end;//保证该条线路都是从end发出
331                     EnQueue(Q, M.bus[b].BusRoute[j]);
332                 }
333             }
334         }
335     }
336     //先把经过该站点的所有公交线路上的站点入队,再一个一个搜索每个站点,直到找到一条线包含start就是最少转车
337 }
338 
339 int main()
340 {
341     BusMap M;
342     CreateMap(M);
343     int start, end;
344     cout<<"请输入起始站点,和最终站点ID:"<<endl;
345     cin >> start >> end;
346     while (GetBusStation(M, start) == 0 || GetBusStation(M, end) == 0)
347     {
348         cout << "站点输入有误!" << endl;
349         cout << "请重新输入起始站点,和最终站点ID:";
350         cin >> start >> end;
351     }
352         
353     FindLeastStationNum(M, start, end);
354     FindLeastTransfer(M, start, end);
355 
356     return 0;
357 }