北京地铁出行路径规划

Posted tutulei

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了北京地铁出行路径规划相关的知识,希望对你有一定的参考价值。

GitHUB源码

GitHUB源码

项目需求

需求1:实现一个支持显示地铁线路与计算换乘的程序
对于地铁路线的数据,将使用subway.txt文件来存储。
对于地铁线路信息图,采用参数 -map 作为标志,例如:

java subway -map subway.txt
需求2:实现地铁线路查询功能
对于地铁线路信息图,采用-a 来指定地铁路线,采用参数 -o 来输出到指定文件station.txt,例如:

java subway -a 1号线 -map subway.txt -o station.txt
需求3:实现最短路径查询
以 -b 参数加两个地铁站点名称分别作为出发与目的,将结果写入 routine.txt,例如:

subway.exe -b 洪湖里 复兴路 -map subway.txt -o routine.txt

具体思路

采用BFS求最短路径,本以为最麻烦的是BFS,后来才发现,数据存储方式,以及换乘站才是最麻烦的部分。

数据存储方式

站点存储格式(Stations中包含所有站点):

public class Station {
    public static HashMap<String, Station> Stations = new HashMap<>();
    private String name;
    private boolean visited =false;
    private Station preStation = null;//just for BFS 
    private List<String> lineBelong = new ArrayList<String>();
    private List<String> nearStations = new ArrayList<String>();
    
    
    public List<String> getNearStations() {
        return nearStations; 
    }
    public void addNearStations(String nearStation) {
        this.nearStations.add(nearStation);
    }
    public String getName() {
        return name;
    }
    public void setName(String name) { 
        this.name = name;
    }
    public boolean isVisited() {
        return visited;
    }
    public void setVisited(boolean visited) {
        this.visited = visited;
    }
    public Station getPreStation() {
        return preStation;
    }
    public void setPreStation(Station preStation) {
        this.preStation = preStation;
    }
    public List<String> getLineBelong() {
        return lineBelong;
    }
    public void addLineBelong(String lineBelong) {
        this.lineBelong.add(lineBelong);
    }
     
     
}

地铁线存储方式(Lines包含所有地铁线号):

public class Line {
    public static HashMap<String, Line> Lines = new HashMap<>();  
    private int id;
    private String name;
    private LinkedList<String> Stations = new LinkedList<>();
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public LinkedList<String> getStations() {
        return Stations;
    }
    public void addStations(String name) {
        this.Stations.add(name);
    }
    
}

其他数据:

public class Parameter {
     public static String FILE_IN=null;
     public static String FILE_OUT=null;
     public static String START_STATION=null;
     public static String END_STATION=null; 
}

首先,使用getSubWayMsg()方法来读取subway.txt中的数据。

public void getSubWayMsg(String filepath) throws Exception { 
         try {
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(new File(filepath)),"UTF-8"));
                String getfileline = null;
                int linecount = 1;
                while ((getfileline = bufferedReader.readLine()) != null) {
                    String[] list = getfileline.split(" ");
                    Line line = new Line();
                    line.setId(linecount++);
                    line.setName(list[0]);
                    String perStation="";
                    String nextStation="";
                    for(int i = 1; i < list.length; i++) {
                        if(i == list.length-1) {
                            nextStation="";
                        }else {
                            nextStation=list[i+1];
                        }
                        if(Station.Stations.containsKey(list[i])) {
                            Station.Stations.get(list[i]).addNearStations(perStation);
                            Station.Stations.get(list[i]).addNearStations(nextStation);
                            Station.Stations.get(list[i]).addLineBelong(line.getName());
                            line.addStations(Station.Stations.get(list[i]).getName());
                        }else {
                            Station station = new Station();
                            station.setName(list[i]);
                            station.addLineBelong(line.getName());
                            station.addNearStations(perStation);
                            station.addNearStations(nextStation);
                            Station.Stations.put(station.getName(), station);
                            line.addStations(station.getName());
                        }
                        perStation=list[i]; 
                    }
                    Line.Lines.put(line.getName(), line);
                    
                }
                bufferedReader.close();
            } catch (Exception e) {
                System.err.println("error: " + e);
            }
            return ;
    }

指定输出某条地铁线:


    public String getLines(String lineName) {
        try {
            Line line = Line.Lines.get(lineName);
            String lineMsg=line.getName()+":";
            for(String name : line.getStations()) {
                lineMsg = lineMsg + "->" + name;
            }
            return lineMsg;
        }catch(Exception e) {
        }
        return null;
        
    }

BFS算法求最短路径:

public void BFS(String st,String ed) {
        for (Station s : Station.Stations.values()) {
            s.setVisited(false);
        }
        Queue<String> queue = new LinkedList<>();
        queue.add(st);
        while(!queue.isEmpty()) {
            String w =queue.poll();
            if(w == ed) {
                break;
            }
            for(String sName : Station.Stations.get(w).getNearStations()) {
                if(sName.equals("")) {
                    continue;
                }
                Station s = Station.Stations.get(sName);
                while(!s.isVisited()) {
                    s.setPreStation(Station.Stations.get(w));
                    s.setVisited(true);
                    queue.add(s.getName());
                }
                
            }
        }
    }

根据bfs中的pre(保存在station中)列出最短路径:

    public List<String> getBestWayMsg() {
        Station s = Station.Stations.get(Parameter.END_STATION);
        List<String> way = new ArrayList<String>();
        while(!s.getName().equals(Parameter.START_STATION)) {
            way.add(s.getName());
            s = s.getPreStation();
        }
        Collections.reverse(way);
        return way;
    }
}

Mian函数功能实现:

public static void main(String[] args) throws Exception{
        boolean isMap = false;
        boolean isGetline = false;
        boolean isPutmsg = false;
        boolean isCheck = false;
        String line ="";
        for(int i = 0; i < args.length; i++){
            
            if(args[i].equals("-map")) {
                Parameter.FILE_IN = args[++i];
                isMap =true;
            }
            else if(args[i].equals("-a")) {
                line = args[++i];
                isGetline =true;
            }
            else if(args[i].equals("-o")) {
                Parameter.FILE_OUT = args[++i];
                isPutmsg =true;
            }
            else if(args[i].equals("-b")) {
                Parameter.START_STATION = args[++i];
                Parameter.END_STATION = args[++i];
                isCheck =true;
            }
            else {
                System.err.print(args[i]);
                System.err.print("erro:"+"请输入正确的命令。");
            }
        }
        if(isMap) {
            Getmsg getmsg = new Getmsg(); 
            getmsg.getSubWayMsg(Parameter.FILE_IN);
            System.out.println("读取"+Parameter.FILE_IN+"的信息成功");
//          for (Line lie : Line.Lines.values()) {
//              System.out.println(lie.getName()+":"); 
//              for(String name : lie.getStations()) {
//                  System.out.print(" "+name);
//              }
//              System.out.println(); 
//          }
        }
        if(isMap&&isGetline&&isPutmsg) {
            Getmsg getmsg = new Getmsg(); 
            String l = getmsg.getLines(line);
//          System.out.print(l);
            try {
                FileWriter fileWriter = new FileWriter(Parameter.FILE_OUT);
                fileWriter.write(l);
                fileWriter.flush();
                fileWriter.close();
            } catch (Exception e) {
                System.err.println("error: "+e);
            }
            
        }
        if(isMap&&isCheck&&isPutmsg) {
            if(Station.Stations.get(Parameter.START_STATION)==null||
                    Station.Stations.get(Parameter.END_STATION)==null) {
                throw new Exception("Error:输入的地铁站有误");
            }
            Getmsg getmsg = new Getmsg();
            getmsg.BFS(Parameter.START_STATION,Parameter.END_STATION);
            List<String> bestWay = getmsg.getBestWayMsg();
             try {
                    FileWriter fileWriter = new FileWriter(Parameter.FILE_OUT);
                    fileWriter.write("总共有(站):");
                    fileWriter.write(bestWay.size() + "
");
                    String NowLine = Station.Stations.get(bestWay.get(0)).getLineBelong().get(0);
                    fileWriter.write(Parameter.START_STATION);
                    for(int i = 0; i < bestWay.size(); i++) {
                        if(Station.Stations.get(bestWay.get(i)).getLineBelong().contains(NowLine)) {
                            fileWriter.write("->" + bestWay.get(i));
                        }
                        else {
                            System.out.println(NowLine);
                            System.out.println(Station.Stations.get(bestWay.get(i)).getLineBelong());
                            
                            fileWriter.write("->" + bestWay.get(i));
                            for(int j = i+1;j< bestWay.size(); j++) {
                                if(Station.Stations.get(bestWay.get(j)).getLineBelong().size()==1){
                                    fileWriter.write("("+NowLine+"转");
                                    NowLine = Station.Stations.get(bestWay.get(j)).getLineBelong().get(0);
                                    fileWriter.write(NowLine+")");
                                    break;
                                }
                                if(Station.Stations.get(bestWay.get(j)).equals(Parameter.END_STATION)) {
                                    break;
                                }
                            }
                            
                            
                        }
                        
                        
                    }
                    fileWriter.flush();
                    fileWriter.close();
             }catch (Exception e) {
                    e.printStackTrace();
             }
        }
        
    }

因为在实际编程中,原计划的文件存储方案不易编写,故数据存储方案稍有改变。

测试效果:

-map subway.txt(从控制台打印Lines,line,Stations,Station):
技术图片

-a 1号线 -map subway.txt -o station.txt
技术图片
-b 鼓楼大街 后沙峪 -map subway.txt -o routine.txt
技术图片

以上是关于北京地铁出行路径规划的主要内容,如果未能解决你的问题,请参考以下文章

北京地铁出行线路规划——代码实现

北京地铁出行规划

北京地铁出行线路规划

北京地铁出行线路规划——个人项目

北京地铁规划项目总结

个人项目关于北京地铁线路出行线路规划