北京地铁线路规划
设计:https://www.cnblogs.com/chenjiji/p/11558885.html
GitHub:https://github.com/Dokenhhh/BJSubway
基本需求
1.获取线路站点信息
2.获取两个站点间的最短路径
代码简析
站点与线路信息采用.txt存储
1 //线路名称
刘园:西横堤 1 //站点距离
西横堤:果酒厂 1
果酒厂:本溪路 1
本溪路:勤俭道 1
勤俭道:洪湖里 1
洪湖里:西站 1
西站:西北角 1
西北角:西南角 1
西南角:二纬路 1
二纬路:海光寺 1
......
实体类设定:
Station为站点类,Result为结果类
站点类Station包含变量:站点名、所属地铁线、相邻站点集合。
结果类Result包含变量:起始站、终止站、距离(站台数)、中间经过站点。
public class Station { private String name; private String line; private List<Station> linkStations = new ArrayList<>(); public String getName() { return name; } public void setName(String name) { this.name = name; } public String getLine() { return line; } public void setLine(String line) { this.line = line; } public List<Station> getLinkStations() { return linkStations; } public void setLinkStations(List<Station> linkStations) { this.linkStations = linkStations; } public Station(String name, String line) { this.name = name; this.line = line; } public Station(String name) { this.name = name; } public Station (){ } public boolean equals(Object obj) { if(this == obj){ return true; } else if(obj instanceof Station){ Station s = (Station) obj; if(s.getName().equals(this.getName())){ return true; } else { return false; } } else { return false; } } public int hashCode() { return this.getName().hashCode(); } public String toString() { return "Station{" + "name='" + name + '\'' + ", line='" + line + '\'' + ", linkStations=" + linkStations + '}'; } } public class Result { private Station star; private Station end; private Double distance = 0.0D; private List<Station> passStations = new ArrayList<>(); public Station getStar() { return star; } public void setStar(Station star) { this.star = star; } public Station getEnd() { return end; } public void setEnd(Station end) { this.end = end; } public Double getDistance() { return distance; } public void setDistance(Double distance) { this.distance = distance; } public List<Station> getPassStations() { return passStations; } public void setPassStations(List<Station> passStations) { this.passStations = passStations; } public Result(Station star, Station end, Double distance) { this.star = star; this.end = end; this.distance = distance; } public Result() { } @Override public String toString() { return "Result{" + "star=" + star + ", end=" + end + ", distance=" + distance + ", passStations=" + passStations + '}'; } }
在这里采用Dijkstra算法进行最短路径的查询
public class DijkstraUtil { private static HashMap<Station, Result> resultMap = new HashMap<>(); private static List<Station> analysisList = new ArrayList<>(); public static Result calculate(Station star, Station end) { if (!analysisList.contains(star)) { analysisList.add(star); } if (star.equals(end)) { Result result = new Result(); result.setDistance(0.0D); result.setEnd(star); result.setStar(star); return resultMap.put(star, result); } if (resultMap.isEmpty()) { List<Station> linkStations = getLinkStations(star); for (Station station : linkStations) { Result result = new Result(); result.setStar(star); result.setEnd(station); String key = star.getName() + ":" + station.getName(); Double distance = DistanceBuilder.getDistance(key); result.setDistance(distance); result.getPassStations().add(station); resultMap.put(station, result); } } Station parent = getNextStation(); if (parent == null) { Result result = new Result(); result.setDistance(0.0D); result.setStar(star); result.setEnd(end); return resultMap.put(end, result); } if (parent.equals(end)) { return resultMap.get(parent); } List<Station> childLinkStations = getLinkStations(parent); for (Station child : childLinkStations) { if (analysisList.contains(child)) { continue; } String key = parent.getName() + ":" + child.getName(); Double distance; distance = DistanceBuilder.getDistance(key); DistanceBuilder.getDistance(key); if (parent.getName().equals(child.getName())) { distance = 0.0D; } Double parentDistance = resultMap.get(parent).getDistance(); distance = doubleAdd(distance, parentDistance); List<Station> parentPassStations = resultMap.get(parent).getPassStations(); Result childResult = resultMap.get(child); if (childResult != null) { if (childResult.getDistance() > distance) { childResult.setDistance(distance); childResult.getPassStations().clear(); childResult.getPassStations().addAll(parentPassStations); childResult.getPassStations().add(child); } } else { childResult = new Result(); childResult.setDistance(distance); childResult.setStar(star); childResult.setEnd(child); childResult.getPassStations().addAll(parentPassStations); childResult.getPassStations().add(child); } resultMap.put(child, childResult); } analysisList.add(parent); return calculate(star, end); } public static List<Station> getLinkStations(Station station) { List<Station> linkedStaions = new ArrayList<Station>(); for (List<Station> line : DistanceBuilder.lineSet) { for (int i = 0; i < line.size(); i++) { if (station.equals(line.get(i))) { if (i == 0) { linkedStaions.add(line.get(i + 1)); } else if (i == (line.size() - 1)) { linkedStaions.add(line.get(i - 1)); } else { linkedStaions.add(line.get(i + 1)); linkedStaions.add(line.get(i - 1)); } } } } return linkedStaions; } private static Station getNextStation() { Double min = Double.MAX_VALUE; Station rets = null; Set<Station> stations = resultMap.keySet(); for (Station station : stations) { if (analysisList.contains(station)) { continue; } Result result = resultMap.get(station); if (result.getDistance() < min) { min = result.getDistance(); rets = result.getEnd(); } } return rets; } private static double doubleAdd(double v1, double v2) { BigDecimal b1 = new BigDecimal(Double.toString(v1)); BigDecimal b2 = new BigDecimal(Double.toString(v2)); return b1.add(b2).doubleValue(); } }
以下为测试样例:
java subway -a 1号线 -map subway.txt -o station.txt
java subway -b 万寿路 七里庄 -map subway.txt -o routine.txt