北京地鐵出行規劃

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

相關文章
相關標籤/搜索