java地铁线路规划_地铁路线规划系统

本文介绍了一个个人项目——地铁路线规划系统的实现,使用Java编程语言。系统通过读取Json格式的地铁线路数据,利用广度优先遍历(BFS)算法寻找两站间的最短路径。内容涵盖了数据存储、数据结构设计、最短路径算法及测试案例。
摘要由CSDN通过智能技术生成

个人项目—地铁路线规划系统设计及实现

问题综述:

b6b2f48ac7ffaa810422ee5b47f82ce3.png

提供一个城市(以北京市为例,如上图地铁线路图所示)的地铁线路图及其相关信息,通过程序计算指定两站之间最短(最少经过站数)乘车路线,输出指定地铁线路的所有站点。首先,将地铁线路信息保存在data.txt中便于理解与使用,具体格式如下:

线路名1 站名1 站名2 站名3 ...

线路名2 站名1 站名2 站名3 ...

线路名3 站名1 站名2 站名3 ...

......

将所有线路名以及站点名都存储在data文件中后,继续之后的功能实现。

需求分析:

输入地铁线路名称,显示整条地铁线路站点

输入两个地铁站名称,并为其规划最短线路并输出

输入某条地铁线路,显示该条线路上的所有站点

若输入的线路或站点不存在,显示错误提示

解决思路:

实现语言:JAVA

收集数据并设计数据存储方式读入数据并构建地铁图的数据结构

设计并确定寻找最短路径算法,以广度优先遍历(BFS)算法为核心算法

使用测试案例对程序进行debug测试

具体实现:

1 数据存储格式及读取

Json格式是一种轻量级的数据交换格式,相对于xml格式比较简洁且易读,因此本项目采用Json格式存储数据(同时,由此本项目在编程是需要使用额外jar包),具体形式如下:

1 {2 "lines": [3 {4 "lineNo": 1,5 "lineName": "1号线",6 "stations": [7 {8 "stationName": "苹果园"

9 },10 {11 "stationName": "古城"

12 },13 ......14 ]15 },16 {17 "lineNo": 2,18 "lineName": "2号线",19 "stations": [20 {21 "stationName": "积水潭"

22 },23 {24 "stationName": "鼓楼大街"

25 },26 ......27 ]28 },29 ......30 {31 "lineNo": 23,32 "lineName": "西郊线",33 "stations": [34 {35 "stationName": "香山"

36 },37      ......38 ]39 }40 ]41 }

将地铁站点数据存放在json文件中,并可利用自建函数readJsonFile读取,其中,readJsonFile函数如下:

1 import java.io.*;2

3 public classReadUtil {4 //读取json文件

5 public staticString readJsonFile(String fileName) {6 String jsonStr = "";7 try{8 //打开文件

9 File jsonFile = newFile(fileName);10 FileReader fileReader = newFileReader(jsonFile);11 Reader reader = new InputStreamReader(new FileInputStream(jsonFile),"utf-8");//一般采用utf-8编码规则

12 int ch = 0;13 StringBuffer sb = newStringBuffer();14 while ((ch = reader.read()) != -1) {15 sb.append((char) ch);16 }17 fileReader.close();18 reader.close();19 jsonStr =sb.toString();20 returnjsonStr;21 } catch(IOException e) {22 e.printStackTrace();23 return null;24 }25 }26 }

2 数据结构方法的确定及应用

将地铁线路图中的每个地铁站点看成一个节点,各个节点之间由地铁线路相连,类似于数据结构“图”中边的存在。因此,本项目将地铁各站点与线路之间的关联类比于“图”的关系,并使用数据结构“图”对地铁线路图进行重建,具体实现代码如下:

SubwayGraph类

1 importjava.io.File;2 importjava.util.ArrayList;3 importjava.util.HashSet;4

5

6 public classSubwayGraph {7 public ArrayList stations=new ArrayList<>();//建立站点List

8 public HashSet edges=new HashSet<>();9

10 public ArrayList getStation() {//获取站点并存入List

11 returnstations;12 }13

14 public intfindStation(String stationName){15 for(int i=0;i

22 public intisInV(Station station){23 for (int i=0;i

31 public void addAdge(int a,int b,intc){32 this.edges.add(newEdge(a,b));33 }34

35 public void addStation(String stationName, int lineNo, intchange){36 //change的值为0表示不可换乘,1表示可换乘

37 int flag=0;38 if (change == 1)39 flag=findStation(stationName);40 if (flag == 0)41 stations.add(newStation(stationName));42 }43

44 public inthashCode() {45 final int prime = 31;46 int result = 1;47 longtemp;48 temp =Double.doubleToLongBits(x);49 result = prime * result + (int) (temp ^ (temp >>> 32));50 temp =Double.doubleToLongBits(y);51 result = prime * result + (int) (temp ^ (temp >>> 32));52 returnresult;53 }54

55 public void addEdge(int u,intv){56 this.edges.add(newEdge(u,v));57 }58

59 public booleanequals(Object obj) {60 if (this ==obj)61 return true;62 if (obj == null)63 return false;64 if (getClass() !=obj.getClass())65 return false;66 MapNode other =(MapNode) obj;67 if (Double.doubleToLongBits(x) !=Double.doubleToLongBits(other.x))68 return false;69 if (Double.doubleToLongBits(y) !=Double.doubleToLongBits(other.y))70 return false;71 return true;72 }73 public HashSetgetEdges(){74 returnedges;75 }76 }

Edge类

1 public classEdge {2 private intu;3 private intstation;4 public Edge(int u,intstation){5 this.u=u;6 this.station=station;7 }8 public intgetU() {9 returnu;10 }11

12 public void setU(intu) {13 this.u =u;14 }15

16 public intgetStation() {17 returnstation;18 }19

20 public void setStation(intstation) {21 this.station =station;22 }23 }

Station类

1 importjava.util.ArrayList;2 importjava.util.HashSet;3

4 public classStation {5 privateString stationName;6 private HashSetline;7 publicStation(String stationName){8 this.stationName=stationName;9 line=new HashSet<>();10 }11

12 publicString getStationName() {13 returnstationName;14 }15

16 public voidsetStationName(String stationName) {17 this.stationName =stationName;18 }19

20 public HashSetgetLine() {21 returnline;22 }23

24 public void addLine(intno) {25 this.line.add(no);26 }27 }

Line类

1 importjava.util.ArrayList;2

3 public classLine {4 private intlineNo;5 privateString lineName;6 private ArrayList stations=new ArrayList<>();7

8 public intgetLineNo() {9 returnlineNo;10 }11

12 public void setLineNo(intlineNo) {13 this.lineNo =lineNo;14 }15

16 publicString getLineName() {17 returnlineName;18 }19

20 public voidsetLineName(String lineName) {21 this.lineName =lineName;22 }23

24 public ArrayListgetStations() {25 returnstations;26 }27

28 public voidaddStations(Station station) {29 this.stations.add(station);30 }31 }

3 类职责分析

类名

方法名

功能职责分析

SubwayGraph

findStation(String stationName)

通过站点名寻找已存储的站点

addStation(String stationName, int lineNo, int change)

添加站点信息,站点信息包括站点名,所属线路编号和是否可以换乘

addEdge(int u,int v)

在图中添加对应于站点的节点

Edge

Edge(int u,int station)

在图中对应站点

getU()

通过输入获取线路信息并先存着

setU(int u)

使用线路信息

getStation()

通过输入获取站点信息并先存着

setStation(int station)

使用站点信息

Station

Station(String stationName)

站点名

getStationName()

获取站点名

setStationName(String stationName)

将站点名压入数组

addLine(int no)

通过json文件读取将站点添加到对应的线路中

Line

getLineNo()

通过输入获取线路编号并先存着

setLineNo(int lineNo)

将线路压入数组

getLineName()

获取线路编号

setLineName(String lineName)

将线路名压入数组

addStations(Station station)

通过json文件读取添加站点

4 最短路径算法的设计与实现

在本项目中,使用使用广度优先遍历(BFS)来寻找最短路径。BFS算法虽然没有dijkstra算法那么完善,但是足以满足寻找两点之间的最短路径值。并将两站点之间的距离换乘不在考虑范围之内,简化了题目的难度。BFS算法的具体实现如下。

1)主函数

1 public classsubway {2 public static void main(String[] args) throwsException {3 ArrayList lines=new ArrayList<>();4 SubwayGraph graph=newSubwayGraph();5 String outputFileName=null;6 String startStation=null;7 String endStation=null;8 String line=null;9 SubwayManager a=newSubwayManager();10 System.out.println(args.length);11 for (int i=0;i

15 lines=a.getLines(fileName);16 graph=a.createGraph(lines);17 i++;18 }19 else if (args[i].equals("-a")){20 line=args[i+1];21 i++;22 }23 else if (args[i].equals("-b")){24 startStation=args[i+1];25 i++;26 endStation=args[i+1];27 i++;28 }29 else if (args[i].equals("-o")){30 outputFileName=args[i+1];31 i++;32 }33 else throw new Exception("输入无效参数");34 }35 if (line!=null){36 ArrayList list = new ArrayList<>();37 for(Line i:lines){38 if(i.getLineName().equals(line)){39 list.add(i.getLineName());40 for(Station station:i.getStations()){41 list.add(station.getStationName());42 }43 }44 }45 a.outputFile(list, outputFileName);46 }else if (startStation!=null&&endStation!=null){47 ArrayList plan=a.Plan(graph,startStation,endStation);48 ArrayList list =a.getChange(plan, lines);49 a.outputFile(list, outputFileName);50 }51 }52 }

2)读取Json文件

1 public ArrayListgetLines(String fileName) {2 ArrayList lines = new ArrayList<>();3 String path = this.getClass().getResource("/" +fileName).getPath();4 JSONObject jobj =JSON.parseObject(ReadUtil.readJsonFile(path));5 JSONArray Jlines = jobj.getJSONArray("lines");6 for (int i = 0; i < Jlines.size(); i++) {7 JSONObject Jline =(JSONObject) Jlines.get(i);8 int lineNo = Jline.getInteger("lineNo");9 String lineName = Jline.getString("lineName");10 JSONArray Jstations = Jline.getJSONArray("stations");11 Line line = newLine();12 line.setLineName(lineName);13 line.setLineNo(lineNo);14 for (int j = 0; j < Jstations.size(); j++) {15 JSONObject station =Jstations.getJSONObject(j);16 line.addStations(new Station(station.getString("stationName")));17 }18 lines.add(line);19 }20 returnlines;21 }

3)BFS核心代码

1 public static booleanbfs(Epax start, Epax end) {2 LinkedList queue = new LinkedList<>();3 queue.addLast(start);

4 while (!queue.isEmpty()) {5 Epax vertex = queue.pollFirst(); //从队首取出一个元素

6 if (vertex.isSerched()) {//如果这个顶点已经完成过检索,则continue跳过

7 continue;8 }9 if (vertex == end) {//如果到了终点,则可以返回了

10 return true;11 }12 else {//如果取出的元素还不是终点,则把该顶点可以到达的邻居顶点全部添加到队尾

13 for(Epax next : vertex.getNext()) {14 if (next.getPredecessor() == null && next !=start) {15 next.setPredecessor(vertex);16 }17 queue.addLast(next);18 }19 }20 vertex.setSerched(true);21 }22 return false;23 }

4)出行方案制定

1 public ArrayListPlan( SubwayGraph graph,String startSation,String endSation) {2 ArrayList plan=null;3 int a=graph.findStation(startSation);4 int b=graph.findStation(endSation);5 if (a==-1||b==-1){6 System.out.println("no Station");7 }else{8 plan=DIJ(graph,a,b);9 }10 returnplan;11 }

5)保存结果

1 public void outputFile(ArrayListlist, String ouputfile) {2 try{3 //相对路径,如果没有则要建立一个新的output.txt文件

4 File writeName = newFile(ouputfile);5 //创建新文件,有同名的文件的话直接覆盖

6 writeName.createNewFile();7 try (FileWriter writer = newFileWriter(writeName);8 BufferedWriter out = newBufferedWriter(writer)9 ) {10 int lineNo = -1;11 for(String i : list) {12 out.write(i + "\r\n");13 }14 out.flush(); //把缓存区内容压入文件

15 }16 } catch(IOException e) {17 e.printStackTrace();18 }19 }

5 对项目程序进行debug测试

使用测试案例对程序进行检验,其中,输出结果输入结果第一行统计一共需要乘坐几个站点,如7(则需要经过7个站点),之后输出经过的站点。若需要换乘,则输出换乘信息。

(无换乘)测试案例

古城 复兴门

结果

11古城

八角游乐园

八宝山

玉泉路

五棵松

万寿路

公主坟

军事博物馆

木樨地

南礼士路

复兴门

(有换乘)测试案例

万寿路 北京西站

结果

6万寿路

公主坟

地铁10号线

莲花桥

六里桥

地铁9号线

六里桥东

北京西站

6 个人总结

本项目简要复习了数据结构和java项目设计的基本流程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值