Beijing subway project plan summary

I. Project Description

  Assist in the realization of a subway travel route planning command-line program.

  github link: https: //github.com/blakeyoungc/subway

  The main requirements: 1, import subway map information

         2, query specifies subway line through the site 

       3, to calculate the shortest distance between the departure from the destination station (after the minimum number of sites) route, and outputs the number of sites and the path (including the starting and the destination site).

 

By Beijing subway map on https://map.bjsubway.com/:

 

 

 Second, the demand to achieve

  

The main module introduces:

No. Module name Features Java class corresponding to
1 The main module (main function) Control of the input parameters Main.java
2 File input and output modules Read txt file Manager.java
3 Shortest path (Dij algorithm) Find the shortest route to achieve two sites Subway.java

 

Input operation performed when the Main function distinguishing different parameters.

 

public class Main {
    public static void main(String[] args)  {
        if(args.length==2||args.length==6||args.length==7) {                        //通过case分别处理不同参数输入时的操作
         switch(args[0]) {
         case "-map":
            Manager.loadfile();
            break;
         case "-a":
            Manager.loadfile(); 
            Manager.searchstations(args[1]);
            break;
         case "-b":
            Manager.loadfile(); 
            Route results=Subway.getRoutine(args[1],args[2]);
            Manager.outputroute(results);
            break;
         }
        }
        else
            System.out.println("格式错误!");
    }
}

 

车站及线路类以及其方法的设计

 

车站类:

import java.util.*;

public class Station {
    private String stationName;                                               //站点名
    private String lineName;                                                  //所在路线名
    private List<Station> linkStations = new ArrayList<>();                   //存储相邻的站点
    public Station(String stationName){
        this.stationName = stationName;
    }

    public Station(String stationName,String lineName){
        this.stationName = stationName;
        this.lineName = lineName;
    }

    public String getStationName() {
        return stationName;
    }

    public void setStationName(String stationName) {
        this.stationName = stationName;
    }

    public String getLineName() {
        return lineName;
    }

    public void setLineName(String lineName) {
        this.lineName = lineName;
    }

    public List<Station> getLinkStations() {
        return linkStations;
    }

    public void setLinkStations(List<Station> linkStations) {
        this.linkStations = linkStations;
    }
}

 

线路类:

public class Route {
    private Station startstation;                                                 //起点
    private Station destination;                                                  //终点
    private List<Station>passedStations=new ArrayList<>();                        //存储最短路径经过的路线站点
    public Station getStartStation() {
        return startstation;
    }

    public void setStartStation(Station startstation) {
        this.startstation = startstation;
    }

    public Station getDestination() {
        return destination;
    }

    public void setDestination(Station destination) {
        this.destination = destination;
    }

    public List<Station> getPassedStations() {
        return passedStations;
    }

    public void setPassedStations(List<Station> passedStations) {
        this.passedStations = passedStations;
    }
}

 

 

需求1、地铁线路图信息的导入

 

程序启动时需要通过读取 -map 参数来获得对应的自定义地铁文件(命名为 subway.txt),从而得到地铁线路图的信息。

示例: java subway -map subway.txt 

通过Hashmap存储subway.txt中的线路站点信息,其中key存线路名,value存站点类的表,存到subwaymap中以供后面使用。

public  static HashMap<String, List<Station>> subwaymap = new HashMap<>();
    public static void loadfile() {
        File file=new File("C://subway.txt");
        try {
            InputStreamReader inputStreamReader=new InputStreamReader(new FileInputStream(file),"GBK");
            BufferedReader reader=new BufferedReader(inputStreamReader);
            String data=null;
            while((data=reader.readLine())!=null) {
            String[] linedata=data.trim().split(" ");                                              //按空格分割读取txt文件的数据
            List<Station>stations=new ArrayList<>();
            for(int i = 1;i<linedata.length;i++){     
                Station station = new Station(linedata[i],linedata[0]);
                stations.add(station);
                }
                subwaymap.put(linedata[0], stations);                                              //按序存入subwaymap
            }
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

 

subway.txt中的北京地铁线路信息截图

 

 

需求2、查询指定地铁线经过的站点。

 

程序启动时需要通过读取 -a 参数来获得线路名,并输出该线路的站点到文件“station.txt”。

示例: -a 10号线 -map subway.txt -o station.txt 

把之前subwaymap中的数据根据用户输入的线路名进行筛选,有序读取该线路经过的站点并写入“station.txt”文件。

public static void searchstations(String routename) {
        File file=new File("C://station.txt");
        try {
            OutputStreamWriter outputStreamWriter = new OutputStreamWriter(new FileOutputStream(file),"GBK");
            BufferedWriter writer = new BufferedWriter(outputStreamWriter);
            List<Station> list = subwaymap.get(routename);    
            writer.write(routename+" ");
                for(int i=0;i<list.size();i++){
                    writer.write(list.get(i).getStationName()+" ");
                        }
                writer.close();
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

   

查询10号线的所有站点,运行完成后station.txt结果截图 

需求3、查询两个站点的最短路径线路及换乘信息

 

程序启动时需要通过读取 -b 参数来获得输入的起点和终点,输出两个站点之间的最短路径经过的站点。

示例: -b 巴沟 土桥 -map subway.txt -o routine.txt 

查询从巴沟到土桥的最短路线站点及换乘线路。

 

通过Dijkstra算法求最短路径。

 

步骤如下:

   1:遍历所有节点找到未访问过的节点中累积权值(其实就是从源节点到当前节点的路径值和)最小的(设为A)。

   2:遍历该节点所有可达边(连通到目标节点B),如果节点A累积权值加可达边权值小于目标节点B自身的累积权值,则对目标节点B进行更新。

   3:将节点A设定为已访问。

   4:重复(1)直到所有节点均访问完毕。

 

public Route Dijkstra(Route routine) {
        Station s;
        Station S;
        HashMap<Station,Station> D = new HashMap<>();
        HashMap<Station,Station> prev = new HashMap<>(); 
        HashMap<Station,Integer> searched = new HashMap<>(); 
        HashMap<HashMap<Station,Station>,Integer> distance = new HashMap<>();                                                      
        for (String key :allStation.keySet()){
            s = allStation.get(key);
            searched.put(s,new Integer(0));
            if (!routine.getStartStation().equals(s)){
                if (routine.getStartStation().getLinkStations().contains(s)){
                    D = new HashMap<>();
                    D.put(routine.getStartStation(),s);
                    distance.put(D,new Integer(1));
                    prev.put(s,routine.getStartStation());
                }
                else{
                    D = new HashMap<>();                              
                    D.put(routine.getStartStation(),s);
                    distance.put(D,new Integer(Integer.MAX_VALUE));
                }
            }
            else{
                D = new HashMap<>();
                D.put(routine.getStartStation(),s);
                distance.put(D,new Integer(0));
            }
        }
        searched.put(routine.getStartStation(),1);
        while (true){
            S = FindMinDist(routine,distance,searched);    
            if (S.getStationName().equals("-1"))
                break;
            searched.put(S,1);
            for (String key:allStation.keySet()){
                if (S.getLinkStations().contains(allStation.get(key))&&searched.get(allStation.get(key))==0){
                    if (distance.get(getFromtoFin(routine,S))+1<distance.get(getFromtoFin(routine,allStation.get(key)))){
                        distance.put(getFromtoFin(routine,allStation.get(key)),distance.get(getFromtoFin(routine,S))+1);
                        prev.put(allStation.get(key),S);
                    }
                }
            }
        }
        S = prev.get(routine.getDestination());
        while(!S.equals(routine.getStartStation())){
            routine.getPassedStations().add(0,S);
            S = prev.get(S);
        }
        routine.getPassedStations().add(0,routine.getStartStation());
        routine.getPassedStations().add(routine.getDestination());
        return routine;
    }

 

通过算法生成最短路径后,再进行换乘线路的判断,同时将数据输出到“routine.txt”文件中。

 

public static void outputroute(Route routine) {
        // TODO Auto-generated method stub
        File file=new File("C://routine.txt");
        try {
            OutputStreamWriter outputStreamWriter = new OutputStreamWriter(new FileOutputStream(file),"GBK");
            BufferedWriter writer = new BufferedWriter(outputStreamWriter);
            writer.write(routine.getPassedStations().size()-1+" ");
            String linename="0";
             for (int i = 0; i < routine.getPassedStations().size();i++)
                {
                    writer.write(routine.getPassedStations().get(i).getStationName()+" ");
                    if (i<routine.getPassedStations().size()-1){
                        if (!routine.getPassedStations().get(i).getLineName().equals(routine.getPassedStations().get(i+1).getLineName())){      //换乘线路的判断
                            linename = routine.getPassedStations().get(i+1).getLineName();
                            if(linename!="0")
                            writer.write("换乘"+linename+"  ");
                        }
                    }
                }
            writer.close();
        }catch(IOException e){
            e.printStackTrace();
        }
    }

 

routine.txt中的最短路线站点及换乘信息

 

异常情况处理:

 

起点与终点相同:-b 土桥 土桥 -map subway.txt -o routine.txt

输出:起点与终点相同

 

起点或终点不存在: -b 123 456 -map subway.txt -o routine.txt

输出:起点或终点不存在

 

查询线路不存在: -a 1000号线 -map subway.txt -o station.txt

输出:线路不存在

 

 

 三、小结

 

本次个人作业中间出现了各种错误,其实还是对java代码的熟悉度不够,实验中多次出现Exception in thread "main" java.lang.NullPointerException的错误,主要因为数组为null了,没有初始化,浪费了很多时间找错,后续还要继续学习熟悉。

 

Guess you like

Origin www.cnblogs.com/31701085yc/p/11661278.html