GitHub地址
https://github.com/31701041/subway
设计思路与模块分析
Station.java
定义了站点Station的类结构和图的结构
public class Station { private String name; //地铁站名称 public Station prev; //前一个站 public Station next; //后一个站 //本站到某一个目标站(key)所经过的所有站集合(value),保持前后顺序 private Map> orderSetMap = new HashMap >(); public Station (String name){ this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } public LinkedHashSet getAllPassedStations(Station station) { if(orderSetMap.get(station) == null){ LinkedHashSet set = new LinkedHashSet (); set.add(this); orderSetMap.put(station, set); } return orderSetMap.get(station); } public Map > getOrderSetMap() { return orderSetMap; } @Override 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; } } @Override public int hashCode() { return this.getName().hashCode(); } }
DataBuilder.java
读取文件,创建地铁路线(得到的是去除了第一列后的站点的集合以及总的站点的数量
得到的站点信息以HashSet> lineSet的形式保存, 每一个list保存的是其中一条线路的信息
public class DataBuilder { public static HashSet> lineSet = new HashSet
>();//所有线集合 public static int totalStaion = 0;//总的站点数量 //读取文件 public static void readFile() throws IOException{ FileInputStream inputStream = new FileInputStream("D:\\Work\\北京地铁\\src\\station.txt"); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); String str = null; while((str = bufferedReader.readLine()) != null) { List
line = new ArrayList (); String[] lineInformations = str.split(" "); for(String s : lineInformations){ line.add(new Station(s)); } line.remove(0); for(int i =0;i ){ if(i ){ line.get(i).next = line.get(i+1); line.get(i+1).prev = line.get(i); } } lineSet.add(line); totalStaion+=line.size(); } inputStream.close(); bufferedReader.close(); } }
StationIncludeLineName.java
读取文件,创建地铁路线(得到的是没有去除了第一列后的set
public class StationIncludeLineName { public static HashSet> lineSet = new HashSet
>();//所有线集合 public static int totalStaion = 0;//总的站点数量 //读取文件 public static void readFile(String fileName) throws IOException{ FileInputStream inputStream = new FileInputStream(fileName); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); String str = null; while((str = bufferedReader.readLine()) != null) { List
line = new ArrayList (); String[] lineInformations = str.split(" "); for(String s : lineInformations){ line.add(new Station(s)); } for(int i =0;i ){ if(i ){ line.get(i).next = line.get(i+1); line.get(i+1).prev = line.get(i); } } lineSet.add(line); totalStaion+=line.size(); } inputStream.close(); bufferedReader.close(); } }
Subway.java
public class Subway { private ListoutList = new ArrayList ();//记录已经分析过的站点 String allStations = ""; //计算从s1站到s2站的最短经过路径, 并输出文件 public String calculate(Station s1, Station s2) { //长度相等级找完了全部的路径,输出文件 if (outList.size() == DataBuilder.totalStaion) { allStations+="找到目标站点:" + s2.getName() + ",共经过" + (s1.getAllPassedStations(s2).size() - 1) + "站"+"\n"; for (Station station : s1.getAllPassedStations(s2)) { allStations+=station.getName() + "->"; } return allStations; } if (!outList.contains(s1)) { outList.add(s1); } //如果起点站的OrderSetMap为空,则第一次用起点站的前后站点初始化之 if (s1.getOrderSetMap().isEmpty()) { List Linkedstations = getAllLinkedStations(s1); for (Station s : Linkedstations) { s1.getAllPassedStations(s).add(s); } } Station parent = getShortestPath(s1);//获取距离起点站s1最近的一个站(有多个的话,随意取一个) if (parent == s2) { allStations+="找到目标站点:" + s2 + ",共经过" + (s1.getAllPassedStations(s2).size() - 1) + "站"+"\n"; for (Station station : s1.getAllPassedStations(s2)) { allStations+=station.getName() + "->"; } return allStations; } for (Station child : getAllLinkedStations(parent)) { if (outList.contains(child)) { continue; } int shortestPath = (s1.getAllPassedStations(parent).size() - 1) + 1;//前面这个1表示计算路径需要去除自身站点,后面这个1表示增加了1站距离 if (s1.getAllPassedStations(child).contains(child)) { //如果s1已经计算过到此child的经过距离,那么比较出最小的距离 if ((s1.getAllPassedStations(child).size() - 1) > shortestPath) { //重置S1到周围各站的最小路径 s1.getAllPassedStations(child).clear(); s1.getAllPassedStations(child).addAll(s1.getAllPassedStations(parent)); s1.getAllPassedStations(child).add(child); } } else { //如果s1还没有计算过到此child的经过距离 s1.getAllPassedStations(child).addAll(s1.getAllPassedStations(parent)); s1.getAllPassedStations(child).add(child); } } outList.add(parent); calculate(s1, s2);//重复计算,往外面站点扩展 return allStations; } //取参数station到各个站的最短距离,相隔1站,距离为1,依次类推 private Station getShortestPath(Station station) { int minPatn = Integer.MAX_VALUE; Station rets = null; for (Station s : station.getOrderSetMap().keySet()) { if (outList.contains(s)) { continue; } LinkedHashSet set = station.getAllPassedStations(s);//参数station到s所经过的所有站点的集合 if (set.size() < minPatn) { minPatn = set.size(); rets = s; } } return rets; } //获取参数station直接相连的所有站,包括交叉线上面的站 private List getAllLinkedStations(Station station) { List linkedStaions = new ArrayList (); for (List line : DataBuilder.lineSet) { if (line.contains(station)) {//如果某一条线包含了此站 Station s = line.get(line.indexOf(station)); if (s.prev != null) { linkedStaions.add(s.prev); } if (s.next != null) { linkedStaions.add(s.next); } } } return linkedStaions; } //文件写入 public static void writeFileString(String strings, String writeFileName) { File fileDir = new File(writeFileName); if(!fileDir.isFile()){ try { fileDir.createNewFile(); } catch (IOException e) { e.printStackTrace(); } } try { FileWriter fw = new FileWriter(fileDir); fw.write(strings); fw.flush(); fw.close(); } catch (IOException e) { e.printStackTrace(); } } public static void main(String[] args) throws IOException { String map = "-map \\S+ "; String line = "-a \\S+ -map \\S+ -o \\S+ "; String path = "-b \\S+ \\S+ -map \\S+ -o \\S+ "; String arge = ""; for (String i : args) { arge += i + " "; } if (arge.matches(map)) { String readFile = args[1]; StationIncludeLineName.readFile(readFile); for (List linename : StationIncludeLineName.lineSet) { for (int i = 0; i < linename.size(); i++) { System.out.print(linename.get(i).getName() + "-->"); } System.out.println(); } } else if (arge.matches(line)) { String lineName = args[1]; String readFile = args[3]; String writeFile = args[5]; StationIncludeLineName.readFile(readFile); Station station = new Station(lineName); String allStations = ""; int flag = 0;//判断是否存在该路线 for (List linename : StationIncludeLineName.lineSet) { if (linename.contains(station)) { allStations+=linename.get(0).getName() + "包括的站点:"+"\n"; for (int i = 1; i < linename.size(); i++) { allStations+=linename.get(i).getName() + "-->"; } flag=1; } } if(flag==0){ System.out.println("该路线不存在"); } else{ writeFileString(allStations, writeFile); } } else if (arge.matches(path)) { String start = args[1]; String end = args[2]; String readFile = args[4]; String writeFile = args[6]; DataBuilder.readFile(readFile); Subway sw = new Subway(); String allStations = sw.calculate(new Station(start), new Station(end)); writeFileString(allStations, writeFile); }else{ System.out.println("输入参数有误"); } } }
测试
需求1
程序启动时需要通过读取 -map 参数来获得对应的自定义地铁文件(命名为 subway.txt),从而得到地铁线路图的信息。
java subway -map subway.txt
需求2
在给定地铁线路时,你的程序就需要能够从线路的起始站点开始,依次输出该地铁线经过的所有站点,直到终点站
java subway -a 1号线 -map subway.txt -o station.txt
需求3
给出起点和终点, 保存路径信息到文件中
subway.exe -b 香山 焦化厂 -map subway.txt -o routine.txt