|
|
# Urban_subway_navigation_system
|
|
|
城市地铁导航系统
|
|
|
摘要:本项目针对城市地铁导航系统问题,可实现的功能有:
|
|
|
1、输出所有地点及其介绍
|
|
|
2、查询某一个地点及其介绍
|
|
|
3、查询某一地点到其他所有地点的最短路径
|
|
|
4、查询某两个地点之间的最短路径
|
|
|
|
|
|
*为有效地存储和处理数据,我们采用了图结构的数据结构。具体来说,我们使用邻接表存储每个站点及其相邻站点的信息,并使用哈希表存储站点名称和编号的映射关系。
|
|
|
*为了找出两点间最短路径,采用了Dijkstra算法,算法效率较高。
|
|
|
*项目的效果从整体来看运行流畅,可以为市民提供方便、快捷的地铁路线查询和导航服务。
|
|
|
*任务分工及工作量占比:(完成情况良好)
|
|
|
| 翟梅瑛 | 连桢钰 | 刘宇婷 | 李文菲 |
|
|
|
| ---- | ---- | ---- | ---- |
|
|
|
| 项目设计 | 代码创建 | 优化改进 | 项目测试 |
|
|
|
| 25% | 25% | 25% | 25% |
|
|
|
|
|
|
#1. 系统分析
|
|
|
##1.1 问题描述
|
|
|
选择北京地铁,建立地铁站点导航地图,设计一个城市地铁导航系统。根据任意指定的两个站点,能够计算出任意两个站点之间路径长度最短的站点导航,并给出换乘方案。
|
|
|
|
|
|
1.2 可行性分析
|
|
|
1.明确解决问题的关键:城市地铁导航系统主要解决的问题是用户在地铁出行过程中需要查询线路、站点等信息,以及如何计算最短路径、如何显示用户当前位置等问题。
|
|
|
2.确定核心数据结构:城市地铁导航系统的核心数据结构是图,将每个地铁站点看作一个节点,每条地铁线路看作一条有向边,通过节点之间的连接表示地铁线路的走向和路径。使用邻接表或邻接矩阵等数据结构来存储图结构。此外,还需要存储地铁站点的位置、经纬度、名称、所属线路等信息。
|
|
|
3.确定核心算法:城市地铁导航系统的核心算法是图论算法,主要包括 Dijkstra 算法、贝尔曼-福德算法和 A* 算法等,用于寻找从起点到终点最短路径。同时还需要对地图进行可视化说明,例如显示沿途经过的地铁站点、换乘点和线路等信息。
|
|
|
|
|
|
4.总体思路和方案:城市地铁导航系统的总体思路和方案如下:
|
|
|
|
|
|
(1)导入地铁数据,包括每个地铁站的名称、位置、经纬度、相邻地铁站之间的距离和所属地铁线路等信息;
|
|
|
(2)构建地铁线路图,使用图论算法对地铁网络进行建模和分析;
|
|
|
(3)寻找路径,用户输入起点站和终点站,程序使用图论算法寻找到两个站之间的一条最短路径;
|
|
|
(4)输出路径,程序将找到的最短路径在地图上用不同颜色的线段标记出来,给用户直观地展示从起点站到终点站沿途经过的所有地铁线路和换乘点;
|
|
|
(5)用户界面设计,为方便用户使用,需要设计一个简洁明了的用户界面,支持用户输入起点站和终点站,展示搜索到的最短路径和沿途经过的地铁线路等信息;
|
|
|
(6)其他功能,例如公交线路查询、建议路径提醒等增强用户体验的功能。
|
|
|
|
|
|
总的来说,城市地铁导航系统需要综合运用数据库、图论算法、用户界面设计等多种技术和工具,才能实现方便、快速、准确的地铁线路查询和导航功能。
|
|
|
1.3 需求分析
|
|
|
(1)输入和输出
|
|
|
输入:用户希望到达的地铁站、出发地铁站、换乘信息、线路信息等。
|
|
|
输出:给用户提供最优路径和换乘信息,告知用户需要哪些线路和站点,预计到达时间等。
|
|
|
(2)数据字典
|
|
|
站点 = 站名 + 站点编号 + 经纬度坐标 + 所属线路
|
|
|
线路 = 线路号 + 站点序列 + 导向信息 + 地铁车类型
|
|
|
路径 = 起点站 + 终点站 + 路径序列 + 总里程 + 总时间
|
|
|
(3)数据文件
|
|
|
需要读取的数据文件:包含站点和线路信息的文件,格式为csv格式,包含字段:站点编号、站名、线路号、经纬度坐标。
|
|
|
需要导出的数据文件:路径信息文件,格式为json格式,包含字段:起点站、终点站、路径序列、总里程、总时间。
|
|
|
(4)参数设定
|
|
|
用户可以通过系统提供的界面输入起点站和终点站信息,以及一些可选参数(如最短时间、最少换乘等)。
|
|
|
(5)路径规划功能
|
|
|
主要作用:根据用户提供的信息,计算最优路径并提供导向信息。
|
|
|
用户输入:起点站、终点站、可选参数(如最短时间、最少换乘等)。
|
|
|
系统输出:最优路径和换乘信息,告知用户需要哪些线路和站点,预计到达时间等。
|
|
|
(6)换乘查询功能
|
|
|
主要作用:查询某个线路的信息。
|
|
|
用户输入:线路号。
|
|
|
系统输出:该线路的信息,包括沿线站点和车站信息、导向信息等。
|
|
|
(7)地图展示功能
|
|
|
主要作用:在地图上展示各个站点和线路的位置和路线。
|
|
|
用户输入:无
|
|
|
系统输出:地铁线路和站点在地图上的显示,方便用户更直观地了解线路位置和路线。
|
|
|
|
|
|
|
|
|
#2. 系统设计
|
|
|
##2.1 概要设计
|
|
|
|
|
|
|
|
|
系统划分为以下模块:
|
|
|
1.用户输入模块:用户通过输入起始站点和终点站点,触发系统查询和计算。
|
|
|
2.数据存储模块:系统将地铁线路和站点信息存储在一个数据结构中,并提供查询和修改功能。
|
|
|
3.路径计算模块:该模块通过获取用户输入的起始站点和终点站点,并利用存储在数据结 构中的地铁线路和站点信息,计算出最优路径。
|
|
|
4.输出模块:该模块将最优路径输出给用户,以便用户按照路径指引乘坐地铁。
|
|
|
2.2 数据结构设计
|
|
|
通过比较邻接矩阵、邻接表、查找表和不相交集等数据结构,我们选择使用邻接表作为数据结构。邻接表具有占用空间小、查询速度快等优势,适合储存大量的地铁线路和站点信息。
|
|
|
邻接表
|
|
|
邻接表是一种表示图形的数据结构,它用于描述地铁网络中的站点之间的连接关系。在邻接表中,每个站点对应一个链表,链表中的每个节点表示与该站点相邻的另一个站点。具体而言,我们可以用如下的结构体表示邻接表中的每个节点:
|
|
|
struct AdjListNode {
|
|
|
int destination; // 相邻站点编号
|
|
|
int weight; // 连接权重(例如两站之间的距离、换乘次数等)
|
|
|
struct AdjListNode* next; // 下一个相邻节点的指针
|
|
|
};
|
|
|
每个链表的头节点可以由一个数组来维护,例如:
|
|
|
|
|
|
struct Station {
|
|
|
char name[20]; // 站点名称
|
|
|
int id; // 站点编号
|
|
|
struct AdjListNode* head; // 相邻节点链表的头节点指针
|
|
|
};
|
|
|
struct Station stations[MAX_STATION_NUM]; // 站点数组
|
|
|
在这个结构中,我们为每个站点记录了它的名称、编号和相邻节点链表的头节点指针。这样的话,我们就可以通过遍历这些链表来获取某一站点的所有邻居站点。同时,由于链表中的每个节点包含了相邻站点的编号和连接权重,因此我们也可以在搜索路径时方便地计算出经过某一条路径的总长度或换乘次数。
|
|
|
|
|
|
|
|
|
2.3 算法设计
|
|
|
我们选择Dijkstra算法作为路径计算模块的核心算法。Dijkstra算法是一种广泛应用于最短路径问题上的算法,具有速度快、结果正确性高、易于实现等优势。它通过不断更新起点到每个点的最短距离,并使用优先队列维护每个点的最短距离,直到计算出终点的最短路径。
|
|
|
Dijkstra算法
|
|
|
用户输入起点站和终点站,程序使用图论算法在地铁线路图中寻找到两个站之间的一条最短路径。此时使用Dijkstra算法找出最短路径。
|
|
|
#3. 系统实现
|
|
|
系统使用C++语言进行开发,使用VScode作为开发工具。
|
|
|
本系统的文件结构如下:
|
|
|
- SubwaySystem
|
|
|
- include
|
|
|
- SubwaySystem.h
|
|
|
- src
|
|
|
- SubwaySystem.cpp
|
|
|
- test
|
|
|
- test.cpp
|
|
|
- CMakeLists.txt
|
|
|
其中,SubwaySystem.h和SubwaySystem.cpp分别实现了地铁系统的数据结构和算法,test.cpp实现了测试用例。
|
|
|
以下是主要函数的功能:
|
|
|
|
|
|
SubwaySystem::addNode(Node node):向地铁系统中添加一个节点。
|
|
|
SubwaySystem::addEdge(Edge edge):向地铁系统中添加一条边。
|
|
|
SubwaySystem::shortestPath(Node from, Node to):计算从起点到终点的最短路径。
|
|
|
|
|
|
|
|
|
##3.1 核心数据结构的实现
|
|
|
数据结构的实现
|
|
|
|
|
|
本系统使用邻接表来表示地铁系统的图。具体实现如下:
|
|
|
|
|
|
|
|
|
struct Node {
|
|
|
int id; // 节点ID
|
|
|
string name; // 节点名称
|
|
|
};
|
|
|
|
|
|
struct Edge {
|
|
|
int from; // 起点ID
|
|
|
int to; // 终点ID
|
|
|
int weight; // 权重(距离)
|
|
|
};
|
|
|
|
|
|
class SubwaySystem {
|
|
|
public:
|
|
|
/ 添加节点和边
|
|
|
void addNode(Node node);
|
|
|
void addEdge(Edge edge);
|
|
|
|
|
|
// 计算两个站点之间的最短路径
|
|
|
vector<Node> shortestPath(Node from, Node to);
|
|
|
|
|
|
private:
|
|
|
// 存储节点和边的数据结构
|
|
|
vector<Node> nodes_;
|
|
|
vector<vector<pair<int, int>>> adjacencyList_;
|
|
|
|
|
|
// 计算从起点到终点的最短路径
|
|
|
vector<int> dijkstra(int from, int to);
|
|
|
};
|
|
|
|
|
|
其中SubwaySystem.h和SubwaySystem.cpp分别实现了地铁系统的数据结构和算法,test.cpp实现了测试用例。
|
|
|
|
|
|
|
|
|
##3.2 核心算法的实现
|
|
|
系统的核心算法主要包括最短路径算法和站点搜索算法。
|
|
|
|
|
|
最短路径算法采用Dijkstra算法实现,该算法的时间复杂度为O(n^2),其中n为站点数。具体实现方式如下:
|
|
|
|
|
|
1.初始化距离dist和最短路径标记visited数组。
|
|
|
2.将起点的距离dist设为0,将visited标记设为false。
|
|
|
3.对于每个未标记的站点,找出距离起点最近的站点v。
|
|
|
4.将v标记为已访问,对于v的每个邻居站点u,如果dist[u]>dist[v]+v到u的距离,更新dist[u]为dist[v]+v到u的距离。
|
|
|
5.重复以上步骤,直到所有站点都被标记为已访问或者没有可访问的站点。
|
|
|
|
|
|
站点搜索算法采用DFS算法实现,该算法的时间复杂度为O(n^2),其中n为站点数。具体实现方式如下:
|
|
|
|
|
|
1.初始化visited数组。
|
|
|
2.从起点出发,采用深度优先搜索方式,访问所有邻居站点。
|
|
|
3.将访问过的站点标记为visited。
|
|
|
4.重复以上步骤,直到找到终点或者没有可访问的站点。
|
|
|
|
|
|
通过以上算法的实现,我们可以实现在地铁图中查找两个站点之间最短路径和查找某个站点的所有邻居站点。
|
|
|
|
|
|
|
|
|
#4. 系统测试
|
|
|
|
|
|
(1)输入:1
|
|
|
结果:输出了所有的站点及简略介绍
|
|
|
(2)输入:2
|
|
|
结果:请问您要查询的地点编号是:10
|
|
|
编号:10
|
|
|
地点:雍和宫
|
|
|
介绍:位于北京市东城区北二环安定门东大街与雍和宫大街、和平里西街交汇处
|
|
|
按任意键返回!
|
|
|
(3)输入:3
|
|
|
结果:请输入查询的地点:3
|
|
|
到达地点 1的总距离为: 30 , 经过路径为:3
|
|
|
到达地点 2的总距离为: 60 , 经过路径为:3--->1--->2
|
|
|
到达地点 3的总距离为: 0 , 经过路径为:3
|
|
|
到达地点 4的总距离为: 100 , 经过路径为:3--->5--->4
|
|
|
到达地点 5的总距离为: 50 , 经过路径为:3--->5
|
|
|
…
|
|
|
(4)输入:4
|
|
|
结果:请输入查询的地点:3
|
|
|
请输入目的地点:5
|
|
|
总距离是: 50 , 经过路径为:3--->5
|
|
|
|
|
|
#5. 总结
|
|
|
我们设计的城市地铁导航系统旨在帮助用户方便快捷地查找和选择地铁线路及站点,并提供实时更新的地铁运行状态和乘车提示。我们在创建项目时遇到的问题有为降低空间复杂度,因而采用邻接表存储结构。Dijkstra的时间复杂度是O(n2),效率并不高,我通过查阅文献的方式了解到可以进一步采用优先队列的思路优化它,在存储时就按照从小到大的顺序实现,这样在选择节点时直接取队首距离最小的节点即可,可以将时间复杂度优化到O(logn)左右 |