内 容:
完成“所需时间最少”换乘路线查询
主要知识点:
数据结构图的最短路径算法
任务:
1.查询出从起点站到终点站用时最少的乘车路线。
2.提供地铁换乘查询,可通过视图方便的查看乘坐路线和换乘路线
3.提供最小出行时间的换乘策略指南
4.提供最小换乘次数的换乘策略指南
一、路径搜索方式
根据地铁线路较为稀疏的特性,暂时仅采用了广度优先搜索(bfs)的方式进行寻路。中途不考虑换乘与时间消耗的情况,仅对经过的点进行存储,在打印时再对所选乘线路进行判断。
1.1广度优先算法理论
广度优先搜索算法(Breadth First Search),又称为"宽度优先搜索"或"横向优先搜索",简称BFS。
它的思想是:从图中某顶点v出发,在访问了v之后依次访问v的各个未曾访问过的邻接点,然后分别从这些邻接点出发依次访问它们的邻接点,并使得“先被访问的顶点的邻接点先于后被访问的顶点的邻接点被访问,直至图中所有已被访问的顶点的邻接点都被访问到。如果此时图中尚有顶点未被访问,则需要另选一个未曾被访问过的顶点作为新的起始点,重复上述过程,直至图中所有顶点都被访问到为止。
换句话说,广度优先搜索遍历图的过程是以v为起点,由近至远,依次访问和v有路径相通且路径长度为1,2...的顶点。下面以"无向图"为例,来对广度优先搜索进行演示。还是以上面的图G1为例进行说明。
DFS:使用栈保存未被检测的结点,结点按照深度优先的次序被访问并依次被压入栈中,并以相反的次序出栈进行新的检测。——类似于树的先根遍历
BFS:使用队列保存未被检测的结点。结点按照宽度优先的次序被访问和进出队列。
——类似于树的按层次遍历的过程
BFS用来搜索最短路径的解法是比较合适的。
比如求最少步数的解,最少交换次数的解,最快走出迷宫等等,因为bfs搜索过程中遇到的第一个解一定是离最初位置最近的,所以遇到第一个解,一定就是最优解,此时搜索算法可以终止。
而如果用dfs,会搜一些其他的位置,需要花相对比较多的时间,需要搜很多次,然后如果找到还不一定是最优解,还要记录这次找的位置,与之后找到的答案进行比较,看看谁才是最优解,这样就比较麻烦。
BFS是浪费空间节省时间,DFS是浪费时间节省空间。
二、代码解析
初始化经过站点队列和站点边队列
stationsList.clear();
edgesList.clear();
首先判断起始站点与终点站不是同一站点
if(s1==s2)
{
stationsList.push_back(s2);
stationsList.push_back(s1);
return true;
}
stationsList为双向队列
std::vector<int> path(stations.size(), -1);
std::vector<double> dist(stations.size(), INF);
dist[s1]=0;
std::priority_queue<Node, std::vector<Node>, std::greater<Node>> priQ;
priQ.push(Node(s1, 0));
while(!priQ.empty())
{
Node top=priQ.top();
priQ.pop();
if(top.stationID==s2)
{
break ;
}
for (int i=0; i<graph[top.stationID].size(); ++i)
{
Node &adjNode=graph[top.stationID][i];
if(top.distance+adjNode.distance<dist[adjNode.stationID])
{
path[adjNode.stationID]=top.stationID;
dist[adjNode.stationID]=top.distance+adjNode.distance;
priQ.push(Node(adjNode.stationID, dist[adjNode.stationID]));
}
}
}
if(path[s2]==-1)
{
return false;
}
int p=s2;
while(path[p]!=-1)
{
stationsList.push_front(p);
edgesList.push_front(Edge(path[p],p));
p=path[p];
}
stationsList.push_front(s1);
dijkstra算法的核心思想流程
1)dist[]存储第i个节点到家的距离,visited[i]=true 代表第i个点是否已经遍历过。
2)遍历所有visited[i] == false的点,找出dist[i]最小的点 k。
3)遍历与k相连的点j,用 min(dist[j], dist[k] + edge[k][j])来更新 dist[j]。
4)将visited[k] = true;
5) 如果还存在点,返回2)