1、北京地鐵線路圖java
station存儲git
/** * 站點名字. */ private String name; /** * 所屬線路. * */ private String line; /** * 相鄰鏈接站點. */ private List<Station> linkStations = new ArrayList<>();
讀取subway.txt而且輸出routinegithub
ublic class subway { public static void main(String[] args) throws IOException { switch (args[0]){ case "-map": //-map subway.txt if(args.length==2){ DistanceBuilder.FILE_PATH = System.getProperty("user.dir") + File.separator + "\\" + args[1]; //根據路徑,讀取地鐵信息,並打印。 DistanceBuilder.readSubway(); System.out.println("成功讀取subway.txt文件"); }else{ System.out.println("驗證參數格式!"); } break; case "-a": //-a 1號線 -map subway.txt -o station.txt if(args.length==6){ DistanceBuilder.FILE_PATH = System.getProperty("user.dir") + File.separator + "\\" + args[3]; DistanceBuilder.WRITE_PATH = System.getProperty("user.dir") + File.separator + "\\" + args[5]; DistanceBuilder.readSubway(); DistanceBuilder.writeLineData(args[1]); System.out.println("已將結果寫入station.txt文件"); }else{ System.out.println("驗證參數格式!"); } break; case "-b": //-b 洪湖裏 復興路 -map subway.txt -o routine.txt if(args.length==7){ DistanceBuilder.FILE_PATH = System.getProperty("user.dir") + File.separator + "\\" + args[4]; DistanceBuilder.WRITE_PATH = System.getProperty("user.dir") + File.separator + "\\" + args[6]; DistanceBuilder.readSubway(); Result result = DijkstraUtil.calculate(new Station(args[1]), new Station(args[2])); DistanceBuilder.writePassStationLine(result); System.out.println("已將結果寫入routine. txt文件"); }else{ System.out.println("驗證參數格式!"); } break; } } }
用迪杰特斯拉算法計算算法
public class DijkstraUtil { /** * 結果集. *resultMap */ private static HashMap<Station, Result> resultMap = new HashMap<>(); /** * 分析過的站點集合. * */ private static List<Station> analysisList = new ArrayList<>(); /** * 迪傑斯特拉算法應用在地鐵的實現. * * @param star the star * @param end the end * @return the result * @since hui_project 1.0.0 */ public static Result calculate(Station star, Station end) { //將開始站點加入到分析過的站點集合。 if (!analysisList.contains(star)) { analysisList.add(star); } //若是開始站點等於終止站點,則設置result,設置距離和station。 if (star.equals(end)) { Result result = new Result(); result.setDistance(0.0D); result.setEnd(star); result.setStar(star); return resultMap.put(star, result); } //第一次調用calculate,且起始點和終止點不一樣,則resultMap爲空。 if (resultMap.isEmpty()) { //第一次調用獲取起始點的相鄰站點(在全部地鐵線中,這裏涉及轉線交叉的周圍站點) List<Station> linkStations = getLinkStations(star); //把相鄰站點集合中的全部站點,加入resultMap中。 由於相鄰,則能夠直接獲取Distance。 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(); //若是resultMap全部點keySet被分析完了,則返回的parent爲null。 if (parent == null) { Result result = new Result(); result.setDistance(0.0D); result.setStar(star); result.setEnd(end); //put方法的返回值就是value值。 return resultMap.put(end, result); } //若是獲得的最佳鄰點與目標點相同,則直接返回最佳鄰點對應的result對象。 if (parent.equals(end)) { return resultMap.get(parent); } //在路徑通過點中加入parent後,更新resultMap集合,要麼起始點通過parent達到parent相鄰點是最優的,要麼起始點到parent相鄰點不可達,而經過parent可達。 //獲取parent對象(最佳點)的相鄰點。 //分析一個parent最佳點後,把它的相鄰點都會加入到resultMap中,在下一次調用getNextStation獲取resultMap中未被標記且距離(起始點到該station的距離)最短。 List<Station> childLinkStations = getLinkStations(parent); //D:B C E 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) { //既能夠A->B,也能夠經過最佳點D,從A->D->B if (childResult.getDistance() > distance) { //若是經過最佳點比直接到距離小,則更新resultMap中的對應result對象。 childResult.setDistance(distance); childResult.getPassStations().clear(); //路徑更新爲A->最佳點->child點。 childResult.getPassStations().addAll(parentPassStations); childResult.getPassStations().add(child); } } else { //若是在resultMap中沒有最佳點的相鄰點,則往resultMap中添加經過最佳點(初始爲起始點的最佳鄰點)到達該點。 childResult = new Result(); childResult.setDistance(distance); childResult.setStar(star); childResult.setEnd(child); childResult.getPassStations().addAll(parentPassStations); childResult.getPassStations().add(child); } resultMap.put(child, childResult); } //初始時,即第一次調用該方法時,在分析點中加入起始點的最佳相鄰點,後面嵌套調用時,就爲獲取某點的最佳鄰點,在用最佳鄰點更新resultMap後,往analysisList中加入最佳鄰點。 analysisList.add(parent); //加入最佳鄰點後,更新resultMap,再次調用calculate return calculate(star, end); //或: // calculate(star, end); 繼續往下走,選擇最佳點,而後更新resultMap。 // return resultMap.get(end); } /** * 獲取全部相鄰節點. * * @param station the station * @return the link stations * @since hui_project 1.0.0 */ //傳入起始點station對象。 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++) { //遍歷每條地鐵線,若地鐵線中存在該站點,則判斷,若是該站點位於地鐵線的起始站,則相鄰站爲地鐵線的第二個站點(i+1), //若是該站點位於地鐵線的最後一個站,則相鄰站爲地鐵線的倒數第二個站點(i-1), //若是該站點位於地鐵線的其他位置,則相鄰站點爲該站點先後位置(i-1/i+1) 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; } /** * 經過計算最小權值 計算下一個須要分析的點 * 將resultMap中的station集合循環遍歷,獲取「未被標記的點(未在analysisList中)」中,對應result對象中距離最小的終點station對象。 * @return the next station * @since hui_project 1.0.0 */ private static Station getNextStation() { Double min = Double.MAX_VALUE; Station rets = null; //獲取resultMap中的station集合。 Set<Station> stations = resultMap.keySet(); for (Station station : stations) { //若是該點被標記爲「已被分析」(已被分析表示起始點到該點的最短路徑已求出) if (analysisList.contains(station)) { continue; } //循環分析resultMap中未被標記的點,求出最短路徑的result對象。 Result result = resultMap.get(station); if (result.getDistance() < min) { min = result.getDistance(); //獲得終點的station對象 rets = result.getEnd(); } } return rets; }
讀取距離信息測試
public static HashMap<String,HashMap<String,Double>> distanceMap = new HashMap<String,HashMap<String,Double>>(); public static LinkedHashSet<List<Station>> lineSet = new LinkedHashSet<>();//全部線集合 public static HashMap<String,List<Station>> lineData; private DistanceBuilder() { } static { createlineData(); } public static void createlineData(){ lineData = new HashMap<>(); for (List<Station> stations : lineSet) { lineData.put(stations.get(1).getLine(),stations); } } public static String getLineNameByStation(Station station){ createlineData(); String startname = station.getName(); for (Map.Entry<String,List<Station>> entry : lineData.entrySet()) { List<Station> stations = entry.getValue(); for (Station sta : stations){ if(sta.getName().equals(startname)){ return entry.getKey(); } } } return ""; }
測試樣例:java subway -b 萬壽路 七裏莊 -map subway.txt -o routine.txtui
github:https://github.com/wuyuhanoch/wuspa