地铁最短路径
项目计划
实现一个通过地铁出行的最短路线规划的命令行程序。
主要功能
1.该程序能够读取.txt文件中的数据,格式如下:
地铁线路总数
线路名1 站名1 站名2 站名3 ...
线路名2 站名1 站名2 站名3 ...
线路名3 站名1 站名2 站名3 ...
2.提供详细的地铁信息查询:在某号线路上,能够查询各个站点的信息,输出该号线路上所有站点信息
3.提供最短路线的计算:在出发站与目的站之间寻求一个路线最短,时间最短,换地铁数最少的路线
项目完成预估表
|
Personal Software Process Stages Time |
Time |
|
计划 |
|
|
估计这个任务需要多少时间 |
1day |
|
开发 |
|
|
· 需求分析 (包括学习新技术) |
3day |
|
· 生成设计文档 |
1day |
|
· 具体设计 |
1day |
|
· 具体编码 |
3day |
|
· 代码复审 |
1day |
|
· 测试(自我测试,修改代码,提交修改) |
1day |
|
报告 |
|
|
· 测试报告 |
1day |
|
· 事后总结, 并提出过程改进计划 |
1day |
实现语言
Java
实现算法
Dijkstra算法
类职责划分
|
· Result |
该类用于存放结果 |
|
· Station |
该类用于存放各站点信息 |
|
· Subway |
主函数启动和输出 |
|
· Data |
用于读取数据和图的创建 |
|
· route |
Dijstra算法求最短路径 |
核心代码
1 package model; 2 3 public class Result { 4 5 private Station start; //起点站 6 private Station end; //终点站 7 private Station pass; //到达该站的最短路径中的上一站 8 private String line; //该站在几号线上 9 private int distance; //几站距离 10 private boolean change; //是否需要换乘 11 public Result() { 12 13 } 14 public Station getStart() { 15 return start; 16 } 17 public void setStart(Station start) { 18 this.start = start; 19 } 20 public Station getEnd() { 21 return end; 22 } 23 public void setEnd(Station end) { 24 this.end = end; 25 } 26 public Station getPass() { 27 return pass; 28 } 29 public void setPass(Station pass) { 30 this.pass = pass; 31 } 32 public String getLine() { 33 return line; 34 } 35 public void setLine(String line) { 36 this.line = line; 37 } 38 public int getDistance() { 39 return distance; 40 } 41 public void setDistance(int distance) { 42 this.distance = distance; 43 } 44 public boolean isChange() { 45 return change; 46 } 47 public void setChange(boolean i) { 48 this.change = i; 49 } 50 51 52 }
1 package model; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 6 public class Station { 7 private String name; //每个站点的名称 8 private List<String> line = new ArrayList<String>(); //每一条地铁线路 9 private List<Station> linkStations = new ArrayList<Station>(); //每一个站点中与之相邻的节点 10 public Station(String name, String linename) { 11 // TODO Auto-generated constructor stub 12 this.name=name; 13 this.line.add(linename); 14 } 15 public String getName() { 16 return name; 17 } 18 public void setName(String name) { 19 this.name = name; 20 } 21 public List<String> getLine() { 22 return line; 23 } 24 public void setLine(List<String> line) { 25 this.line = line; 26 } 27 public List<Station> getLinkStations() { 28 return linkStations; 29 } 30 public void setLinkStations(List<Station> linkStations) { 31 this.linkStations = linkStations; 32 } 33 }
public class Data { public Data(String pathname) throws IOException{ File filename = new File(pathname); InputStreamReader reader = new InputStreamReader(new FileInputStream(filename)); //读取地图文件 BufferedReader br = new BufferedReader(reader); String content=""; content=br.readLine(); int linenum=Integer.parseInt(content); //linenum为地图中地铁总线数 for(int i=0;i<linenum;i++) { //向图中添加地铁线路 content=br.readLine(); List<Station> line=new ArrayList<Station>(); String[] linelist=content.split(" "); //去空格 String linename=linelist[0]; //读取线路的名称 for(int j=1;j<linelist.length;j++) { //向每条线路中添加站点 int flag=0; for(List<Station> l:lineSet) { //遍历线路集合 int t; for(t=0;t<l.size();t++) { if(l.get(t).getName().equals(linelist[j])) { //寻找换乘站进行处理 List<String> changelist=l.get(t).getLine(); changelist.add(linename); //向换乘列表内添加可以换乘的站点名字 l.get(t).setLine(changelist); line.add(l.get(t)); flag=1; //找到最近换乘点,跳出遍历 break; } } } if(linelist[j].equals(linelist[1])) { //添加站点名和起始站点名一致时,判断其为环线 line.get(0).getLinkStations().add(line.get(line.size()-1)); line.get(line.size()-1).getLinkStations().add(line.get(0)); flag=1; } if(flag==0) line.add(new Station(linelist[j],linename)); //既不是环线也不是换乘点直接添加 } for(int j=0;j<line.size();j++) { //添加每个车站相邻的车站 List<Station> newlinkStations=line.get(j).getLinkStations(); if(j==0) { //该站为起始站 newlinkStations.add(line.get(j+1)); line.get(j).setLinkStations(newlinkStations); } else if(j==line.size()-1) { //该站为终点站 newlinkStations.add(line.get(j-1)); line.get(j).setLinkStations(newlinkStations); } else { //中间站 newlinkStations.add(line.get(j+1)); newlinkStations.add(line.get(j-1)); line.get(j).setLinkStations(newlinkStations); } } lineSet.add(line); } br.close(); } }
1 public class route { 2 private static List<Station> listA= new ArrayList<>(); 3 private static HashMap<Station, Result> resultMap = new HashMap<>(); //结果集 4 private static Station getNextStation() { 5 int min=999999; //初始化最短路径 6 Station nextStation = null; 7 Set<Station> stations = resultMap.keySet(); 8 for (Station station : stations) { 9 if (listA.contains(station)) { //过滤掉已经包含的站点名 10 continue; 11 } 12 Result result = resultMap.get(station); 13 if (result.getDistance() < min) { //判断其是否最短 14 min = result.getDistance(); 15 nextStation = result.getEnd(); 16 } 17 } 18 return nextStation; 19 } 20 21 public static List<Station> getAllStation(String linename){ //获取路线上的全部站点 22 int flag=1; 23 for (List<Station> listall:Data.lineSet) { 24 for(Station s :listall) { 25 if(!s.getLine().contains(linename)) 26 flag=0; 27 } 28 if(flag==1) 29 return listall; 30 else 31 return null; 32 } 33 return null; 34 } 35 36 public static Result shortestPath(Station start, Station end) { //用dijstra算法计算最短路径 37 for(List<Station> l:Data.lineSet) { //构造结果集 38 for(int i=0;i<l.size();i++) { 39 Result result = new Result(); 40 result.setStart(start); 41 result.setEnd(l.get(i)); 42 result.setDistance(999999); 43 result.setChange(false); 44 resultMap.put(l.get(i), result); 45 } 46 } 47 for(Station s:start.getLinkStations()) { //初始化结果集 48 resultMap.get(s).setDistance(1); 49 resultMap.get(s).setPass(start); 50 List<String> changelines=getChangeLine(start.getLine(),s.getLine()); 51 resultMap.get(s).setLine(changelines.get(0)); 52 } 53 resultMap.get(start).setDistance(0); 54 listA.add(start); //添加起始站 55 Station nextstation = getNextStation(); 56 while(nextstation!=null) { //对每一个站点进行遍历,计算最短路径 57 for(Station s:nextstation.getLinkStations()) { 58 if(resultMap.get(nextstation).getDistance()+1<resultMap.get(s).getDistance()) { 59 resultMap.get(s).setDistance(resultMap.get(nextstation).getDistance()+1); 60 resultMap.get(s).setPass(nextstation); 61 //判断是否在原来线路上,即是否需要换乘 62 List<String> changelines=getChangeLine(nextstation.getLine(),s.getLine()); 63 if(!changelines.contains(resultMap.get(nextstation).getLine())) { 64 resultMap.get(s).setLine(changelines.get(0)); 65 resultMap.get(s).setChange(true); 66 } 67 else { 68 resultMap.get(s).setLine(resultMap.get(nextstation).getLine()); 69 } 70 } 71 } 72 listA.add(nextstation); 73 nextstation = getNextStation(); 74 } 75 return resultMap.get(end); 76 } 77 78 }
运行效果
通过-a命令显示一条线路上的所有站点



通过-b命令查询最短路径
1.同一条线路两站间查询

2.换乘查询

异常处理

总结
程序做起来还是比想象中更复杂一些,对java的各个类也有了更深入的了解,也更清晰的感受到了自己的不足。
整个程序基本能够正常运行,但还是存在较多漏洞,还有较多没考虑到的情况,还有待加强
Git地址
https://github.com/zzzmmmzzz/Subway