北京地铁出行线路规划系统项目总结

项目需求

实现一个帮助进行地铁出行路线规划的命令行程序

地铁线路图数据需要与执行程序解耦

支持查询单条线路的所有站点

支持查询任意两站之间通过最少站数的路线

算法设计

项目中最主要的点在于:找出两个站点之间通过最少站数的路线。该点对应的经典模型是“在一个无向图中找出两点之间的最短路径”。各个站点即为无向图中的点,两站间的路径即为无向图中连接两个节点的边,在此需求下,所有边的长度均为1。

地铁最短路的换乘,最贴近实际的情况是“一次初始化,多次查询”,即在地图确定下来之后可能会有若干次不同点对的查询。而本需求中地铁线路图数据需要与执行程序解耦,每次查询对于地图数据都可能是不同的,所以初始化的时间应该均摊到每次查询中去。由于地铁地图属于稀疏图,且该图中每条边权恒定,故可以直接使用BFS算法解决。

细节上,为了解决两条线路覆盖的情况下(见下图),连续换乘的问题,需要更好的换乘算法。

解决方法:通过判断站点和前继站点的所在线路是否有重叠来判断是否需要换乘。

存储设计

数据存储上,可以采用存点/存边两种形式。在本项目中,存边会明显优于存点。

简洁易懂。数据中每个条目表示两个站点中的一条通路。

易于扩展。添加站点方便;数据不需要有序。

方便应用程度读取。数据中每个条目即为图中的一条边,方便建图。

具体到内容,整个数据文件可以被几条线路分成几个大的模块,每个模块存一条线路的数据,由于地铁站名不存在同名的情况,可以不存线路换乘站点的信息,通过同名同名判断即可。由于同一条边不可能同时属于两条线路,所以在边信息上不会存在冗余。每个模块由一个星号(*)开始,后面这个这条线的名称。接下来包含若干条边信息。每条边信息的格式为起点站名称 终点站名称。每条线的起点可以由建图后入度为 0 的点确定。

样例如下:

* 1号线

刘院 西横堤

果酒场 本溪路

...(省略)

咸水沽北 双桥河

* 9号线

天津站 大王庄

大王庄 十一经路

...(省略)

架构设计

系统整体的计算核心使用Java实现,通过命令行可以与之进行数据交互,通过指定地图数据和相关查询指令,可以实现所有的需求。同时,该核心可以通过外加另外的展示模块来实现人机交互的可视化。外加的数据显示模块采用B/S架构,后端使用Python/Flask实现,前端使用Node.js/Vue.js实现,前后端分离,两者使用接口进行数据交互。

实现细节

计算核心

数据初始化

private static void dataInit(String pathname) {

try(FileReader reader = new FileReader(pathname); BufferedReader br = new BufferedReader(reader) ) {

String line;

String lineName="";

boolean first=false;

while((line=br.readLine()) != null) {

String[] data = line.split(" ");

if(data[0].contains("*")){

lineName=data[1];

first=true;

continue;

}

int id1=getStationId(data[0]);

int id2=getStationId(data[1]);

if(first){

lineStart.put(lineName, id1);

first=false;

stations.get(id1).addLines(lineName);

}

stations.get(id2).addLines(lineName);

addEdge(id1, id2, lineName);

}

Station.count=stationCnt;

} catch (Exception e) {

e.printStackTrace();

}

}

通过约定的数据存储格式进行数据初始化,通过 * 星号来区别不同线路的数据。每条数据表示地铁图上的一条边,通过记录边数据和对应的线路名称来建立地铁图。

换乘检测

private static String checkSwitchLine(int id1, int id2, int id3){

String linea=edgeLines.get(getEdgeHash(id1,id2));

String lineb=edgeLines.get(getEdgeHash(id2,id3));

if(linea.equals(lineb)) return null;

return lineb;

}

通过检测相邻两条表是否同属于同一条线路来判断是否需要换乘。

路径查询

private static void getShortestPath(String start, String end) throws IOException {

int startID=getStationId(start);

if(startID>Station.count){

println("错误:没有 " + start + " 这个站");

return;

}

int endID=getStationId(end);

if(endID>Station.count){

println("错误:没有 " + end + " 这个站");

return;

}

Queueq=new LinkedList<>();

q.offer(startID);

stations.get(startID).setVis(true);

while(!q.isEmpty()){

Station now=stations.get(q.poll());

for(int it:now.getEdges()){

Station tmp=stations.get(it);

if(tmp.isVis()) continue;

q.offer(it);

tmp.setVis(true);

tmp.setLastPoint(now.getId());

if(it==endID) break;

}

}

Stack path=new Stack<>();

int tip=endID;

while(tip!=startID){

path.push(tip);

tip=stations.get(tip).getLastPoint();

}

ArrayList res=new ArrayList<>();

res.add(startID);

while(!path.empty()){

int now=path.pop();

res.add(now);

}

println(res.size());

int tmpa=-1,tmpb=-1;

for(int it:res){

if(tmpa!=-1){

String switchMsg=checkSwitchLine(tmpa,tmpb,it);

if(switchMsg!=null){

println(switchMsg);

}

}

println(stations.get(it).getName());

tmpa=tmpb;

tmpb=it;

}

}

通过BFS算法进行最短路的寻路。找到路径之后检测路径上的所有站点是否需要换乘。

后端接口

后端接口由Python/Flask实现。Flask是一个轻量级的web框架,在接口类后端应用上有很大的优势。

全局数据接口

@app.route('/data', methods=['GET'])

def data():

lines = []

sites = set()

file = open('subway.txt', 'r')

for item in file:

ll = item.strip().split()

if ll[0].find('*') != -1:

lines.append(ll[1])

else:

sites.add(ll[0])

sites.add(ll[1])

return jsonify({

'lines': lines,

'sites': list(sites)

})

该接口用于查询地铁图中出现的所有线路和所有站点的列表,通过直接读取数据文件实现。

查询接口

GET_ALL_CMD = 'java subway -map subway.txt -a %s -o out.txt'

GET_PATH_CMD = 'java subway -map subway.txt -b %s %s -o out.txt'

@app.route('/query', methods=['POST'])

def query():

json_data = request.get_json()

all = json_data['isAll']

if all:

os.system(GET_ALL_CMD % json_data['query'])

else:

os.system(GET_PATH_CMD % (json_data['query'][0], json_data['query'][1]))

file = open('out.txt', 'r')

res = []

for item in file:

res.append(item.strip())

return jsonify({

'res': res

})

该接口通过前端提交的数据,选择查询线路和查询路径对应的计算核心命令,来使用计算核心来获取线路数据。

前端页面

前端页面是用户和程序交互的非常重要的手段。本项目的前端页面使用Vue.js配合ElementUI实现。

运行效果

计算核心

通过-a命令显示一条线上所有的站点。

通过-b命令查询两站之间的最短路径。

通过-o命令指定结果输出的文件。

计算核心的健壮性:不合法命令的检测。

WEB展示前端

查询主界面。(路径查询)

当查询时,输入关键字,系统将会自动匹配补全相关的站点供用户选择。

查询的结果。显示每一站的站名,并在需要换乘的站点后面标注换乘的线路。

线路站点查询,可以查询每条线路所包含的所有站点。

线路查询结果。

线路规划实现用java_北京地铁出行线路规划系统项目总结(Java+Flask+Vue实现)相关推荐

  1. 天津地铁出行线路规划项目需求分析与设计思路分析

    天津地铁出行线路规划项目需求分析与设计思路分析 项目概要 以下是天津地铁线路总图,本项目的受众可以通过本软件,获得天津市地铁出行最便捷,最快速的线路推荐. 需求分析 实现一个帮助进行地铁出行路线规划的 ...

  2. 个人项目-地铁出行线路规划程序

    欢迎大家关注我们的软工团队:http://www.cnblogs.com/Default1406/ PSP表格 PSP 2.1 Personal Software Process Stages Pla ...

  3. 地铁出行线路规划项目需求分析与设计

    项目需求 实现一个帮助进行地铁出行路线规划的命令行程序 地铁线路图数据需要与执行程序解耦 支持查询单条线路的所有站点 支持查询任意两站之间通过最少站数的路线 算法设计 项目中最主要的点在于:找出两个站 ...

  4. enumerable java_基于Java8的LINQ开源项目:Java Enumerable

    微软推出的LINQ曾经领先Java很长一段时间,如今随着Java 8的lambdas推出,Java总算赶上来,streams有如下方法: map filter flatMap distinct sor ...

  5. 预培训-个人项目(地铁出行规划)

    预培训-个人项目(地铁出行线路规划) 项目原址: https://edu.cnblogs.com/campus/buaa/2019BUAASummerSETraining/homework/3407 ...

  6. 地铁出行规划项目分析

    地铁出行规划项目分析 基本理解 本次个人项目是实现一个帮助进行地铁出行线路规划的命令行程序,在程序开始需要导入地铁线路图,然后有查询相关线路信息和经过最少站点到达目的地的功能,由于在本项目中可以忽略站 ...

  7. 高德地图之反地理编码、线路规划、天气查询

    地理编码和反地理编码 /*** 地理编码和反地理编码*/private void geoSearch() {//地理编码GeocodeSearch geocoderSearch = new Geoco ...

  8. Android开发之高德API篇:2、高德API线路规划

    TIME:2020年7月6日 2.高德API线路规划----步行线路规划 前言: step1 工程配置 step2 整体实现过程 step3 具体实现过程 总结 附上源码 前言: 该篇博客主要是介绍高 ...

  9. Android 高德地图自定义线路规划选择方案之后按照方案进行导航

    Android 高德地图自定义线路规划选择方案之后按照方案进行导航 因为我这边导航需求的问题,导致我这边不能使用高德地图官方的线路规划和导航.所以我这边线路规划和导航界面都是根据高德地图那边给的api ...

  10. java地铁线路规划_地铁线路规划——简单分析

    计算地铁线路最短路径 我们要将地铁线路信息等用一个文本文件的形式保存起来,应保存的信息应包括地铁线路名称.各个地铁站点的名称以及车站换乘信息,使得应用程序可以通过读取这个文件,就能掌握关于北京地铁线路 ...

最新文章

  1. 自定义listview
  2. mysql忘记root密码及修改密码
  3. keepalived之 Keepalived 原理(定义、VRRP 协议、VRRP 工作机制)
  4. RouterOs建立PPPoE虚拟拨号服务器
  5. 搭建好看的静态博客(使用Hexo进行搭建)
  6. scikit-learn学习笔记(六)Decision Trees(决策树)
  7. oracle数据库常用的语法与复合函数
  8. yang模型中rpc_领域驱动模型(DDD)设计讲解
  9. 手机运行速度慢怎么办
  10. 移动支付--银联,支付宝,微信(android)
  11. 使用 Visual Studio 2012进行C语言开发
  12. OpenCV教程(42) xml/yaml文件的读写
  13. MyBatis学习第一步
  14. Vijos-p1154买蛋糕(dfs + 剪枝)
  15. 精确度,召回率,真阳性,假阳性
  16. JavaScript期末大作业 罗兰永恒花园动漫价绍网页 7页,含有table表格,js表单验证还有首页视频
  17. Excel 2010 VBA 入门 014 获取VBA帮助
  18. TP-LINK路由器作为副路由器之Lan接口连接详解
  19. Golang的大端序和小端序
  20. 2.4G遥控感应橱柜灯酒柜氛围灯

热门文章

  1. mysql 迁移 myd_mysql文件*.opt *.frm *.MYI *.MYD的迁移
  2. 筋膜枪有感电机和无感电机是什么意思?如何区别
  3. 如何将桌面上的qlv格式转换成mp4视频
  4. 算术平均数、几何平均数、调和平均数的、标准差、方差、正态分布、异常值噪声处理
  5. javascript学习心得
  6. 【Vue】以登录token为例,理解vuex状态管理使用
  7. 透明OLED显示器的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告
  8. jenkins Process leaked file descriptors
  9. JAVA proxy dns回源_常见问题 - CDN 回源配置相关问题
  10. Ubuntu内核版本降级