Welcome to my blog!

地铁线路最短路径

地铁路线最短路径

项目介绍:

主要功能:

 

提供一副地铁线路图,计算指定两站之间最短(最少经过站数)乘车路线;输出指定地铁线路的所有站点。以北京地铁为例,地铁线路信息保存在data.txt中,格式如下:

地铁线路总数

线路名1 站名1 站名2 站名3 ...

线路名2 站名1 站名2 站名3 ...

线路名3 站名1 站名2 站名3 ......

 

需求分析:

 

1、能够为用户在短时间内罗列出最佳的路线。

 

2、能够显示列出路线所要经过的站点。

 

3、用户输入路线号显示该路线所有站点使得用户能够查看。

实现语言:

本次作业使用Java语言编写

实现算法:

 针对本次任务使用Dijkstra算法,在无向图从一点到另一点,遍历路径的过程中若到集合中的点的距离变小则更新到该点的距离,直到到达所要求的点。

 

类职责划分(将相关类的功能进行描述):

职责
Station 站点信息
Line 线路信息
Dijkstra 计算最短路径
main 地铁线路的读取、存储和选择查询功能

 

 

 

 

 

 

核心代码(将所有类的代码标注并提交):

 Station(存放站点)

 

public class Station {
    private String station_name;  //站点名
    private List<String> station_line=new ArrayList<String>();  //所在线路(换乘站有多条)
    private List<Station> near_stations=new ArrayList<Station>();  //与之相邻的站点
    public String getStation_name() {
        return station_name;
    }
    public void setStation_name(String station_name) {
        this.station_name = station_name;
    }
    public List<String> getStation_line() {
        return station_line;
    }
    public void setStation_line(List<String> station_line) {
        this.station_line = station_line;
    }
    public List<Station> getNear_stations() {
        return near_stations;
    }
    public void setNear_stations(List<Station> near_stations) {
        this.near_stations = near_stations;
    }
    
}

 Line(存放线路)

 

public class Line {
    private Station line_start;  //线路起始站
    private Station line_end;   //线路终点站
    private int distance;  //距离
    private Station front_station;  //到达该站的最短路径中的上一站
    private String line_name;   //路线名称
    private int line_change;  //标记从上一站到该站是否有换乘,0为无换乘,1为需换乘
    private List<Station> stations=new ArrayList<Station>();//记录站点
    
    public List<Station> getStations() {
        return stations;
    }
    public void setStations(List<Station> stations) {
        this.stations = stations;
    }
    public Station getLine_start() {
        return line_start;
    }
    public void setLine_start(Station line_start) {
        this.line_start = line_start;
    }
    public Station getLine_end() {
        return line_end;
    }
    public void setLine_end(Station line_end) {
        this.line_end = line_end;
    }
    public int getDistance() {
        return distance;
    }
    public void setDistance(int distance) {
        this.distance = distance;
    }
    public Station getFront_station() {
        return front_station;
    }
    public void setFront_station(Station front_station) {
        this.front_station = front_station;
    }
    public String getLine_name() {
        return line_name;
    }
    public void setLine_name(String line_name) {
        this.line_name = line_name;
    }
    public int getLine_change() {
        return line_change;
    }
    public void setLine_change(int line_change) {
        this.line_change = line_change;
    }
}

 

Subway(包含文件读取、存储和计算最短路径)

public class subway {
    public static void main(String[] args) throws IOException {
        public static LinkedHashSet<List<Station>> lineSet = new LinkedHashSet<List<Station>>();   //线路集合
        System.out.print("请输入地铁路线文档路径:");
        //D:\programdistg\java file\eclipse-wokespace\shortest_path\src\地铁线路信息.txt
        Scanner path=new Scanner(System.in);
        File file=new File(path.nextLine());//读取地铁路线文件
        if(!file.exists()) throw new FileNotFoundException("文件路径有误");
        Line lines=new Line();
        Station stations=new Station();
        BufferedReader br=new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"));//规定字符集以免出现乱码
        String content="";
        content=br.readLine();
        int linenum=Integer.parseInt(content);
        for(int i=0;i<linenum;i++) {  //循环往lineSet中添加line
            content=br.readLine();
            List<Station> line=new ArrayList<Station>();
            String[] splits=content.split(" "); 
            String linename=splits[0];
            for(int j=1;j<splits.length;j++) {  //循环往line中添加station
                int flag=0;
                for(List<Station> l:lineSet) {  //处理换乘站
                    for(int k=0;k<l.size();k++) {
                        if(l.get(k).getName().equals(splits[j])) {  
                            List<String> newline=l.get(k).getLine();
                            newline.add(linename);
                            l.get(k).setLine(newline);
                            line.add(l.get(k));
                            flag=1;
                            break;
                        }
                    }
                    if(flag==1)
                        break;
                }
                if(j==splits.length-1&&splits[j].equals(splits[1])) {  //处理环线
                    line.get(0).getLinkStations().add(line.get(line.size()-1));
                    line.get(line.size()-1).getLinkStations().add(line.get(0));
                    flag=1;
                }
                if(flag==0)
                    line.add(new Station(splits[j],linename));
            }
            for(int j=0;j<line.size();j++) {  //初始化每个车站相邻的车站
                List<Station> newlinkStations=line.get(j).getLinkStations();
                if(j==0) {
                    newlinkStations.add(line.get(j+1));
                    line.get(j).setNear_stations(newlinkStations);
                }
                else if(j==line.size()-1) {
                    newlinkStations.add(line.get(j-1));
                    line.get(j).setNear_stations(newlinkStations);
                }
                else {
                    newlinkStations.add(line.get(j+1));
                    newlinkStations.add(line.get(j-1));
                    line.get(j).setNear_stations(newlinkStations);
                }
            }
            lineSet.add(line); 
        }
        br.close();
        System.out.print("选择要查询的类别 1、查询线路2、查询最短路径");
        int choice=path.nextInt();
        if(choice==1) {
            sysytem.out.print("请输入要查询的路线");
            String line_name=path.next();
            int flag=1;
            for(Line line:lines) {
                if(line.getLine_name().equals(line_name))
                    {
                        System.out.print(lines.getStations().toString());//根据所存的数组直接输出
                        flag=0;
                        break;
                    }
            }
            if(flag==1) {
                System.out.print("线路名输入有误");
            }
        }
        else if(choice==2)
        System.out.print("请输入起始站:");
        String start_stationt_station_name=path.next();
        System.out.print("请输入终点站:");
        String line_end_station_name=path.next();
        Station start_stationt_station = new Station();
        Station line_end_station = new Station();
        for(Station station:stations) {
            if(station.getStation_name().equals(start_stationt_station_name)) {
                start_stationt_station=station;
            }
            if(station.getStation_name().equals(line_end_station_name))
                line_end_station=station;
        }
        ArrayList<Station> shortestPath=new ArrayList<Station>();
        showPath(line_end_station,shortestPath);
        String changeLine=getSameLine(shortestPath.get(0),shortestPath.get(1));
        for(int i=0;i<shortestPath.size();i++) {
            if(i>=2) {
                if(!getSameLine(shortestPath.get(i),shortestPath.get(i-1)).equals(changeLine)) {
                    changeLine=getSameLine(shortestPath.get(i),shortestPath.get(i-1));
                    System.out.print("  ------->换乘  "+changeLine);
                }
            }
            System.out.println(shortestPath.get(i).getStation_name()+"  ");
        }
        }
        else {
            System.out.print("输入有误,请重试");
        }
    public static Dijkstra(Station start_station, Station end_station) {  //dijkstra算法计算最短路径
        private static List<Station> analysisList = new ArrayList<>();        //已经分析过的站点
        private static HashMap<Station,Line> LineMap = new HashMap<>();  //结果集
        private static Station getNextStation() {    //获取下一个需要分析的站点
            int dist=999999;
            Station rets = null;
            Set<Station> stations = LineMap.keySet();
            for (Station station : stations) {
                if (analysisList.contains(station)) {
                    continue;
                }
                Line Line = LineMap.get(station);
                if (Line.getDistance() < dist) {
                    dist = Line.getDistance();
                    rets = Line.getline_end();
                }
            }
        for(List<Station> l:DataBuilder.lineSet) {  //构造结果集
        for(int k=0;k<l.size();k++) {
            Line Line = new Line();
            Line.setstart_station(start_station);
            Line.setline_end(l.get(k));
            Line.setDistance(999999);
            Line.setLine_change(0);
            LineMap.put(l.get(k), Line);
        }
    }
    for(Station s:start_station.getLinkStations()) {  //初始化结果集
        LineMap.get(s).setDistance(1);
        LineMap.get(s).setPassStations(start_station);
        List<String> samelines=getSameLine(start_station.getLine(),s.getLine());
        LineMap.get(s).setLine(samelines.get(0));
    }
    LineMap.get(start_station).setDistance(0);
    analysisList.add(start_station);
    Station nextstation = getNextStation();         //计算下一个需要分析的站点
    while(nextstation!=null) {  //循环计算每一个站点的最短路径
        for(Station s:nextstation.getnear_stations()) {
            if(LineMap.get(nextstation).getDistance()+1<LineMap.get(s).getDistance()) {  //更新最短路径
                LineMap.get(s).setDistance(LineMap.get(nextstation).getDistance()+1);
                LineMap.get(s).setPassStations(nextstation);
                List<String> samelines=getSameLine(nextstation.getLine(),s.getLine());
                if(!samelines.contains(LineMap.get(nextstation).getLine())) {  //需要换乘
                    LineMap.get(s).setLine(samelines.get(0));
                    LineMap.get(s).setLinechange(1);
                }
                else {
                    LineMap.get(s).setLine(LineMap.get(nextstation).getLine());
                }
            }
        }
        analysisList.add(nextstation); 
        nextstation = getNextStation();
    } 
    int flag=1;
    for (List<Station> l:DataBuilder.lineSet) {
        flag=1;
        for(Station s :l) {
            if(!s.getLine().contains(linename))
                flag=0;
        }
        if(flag==1)
            return l;
    }    
    return null;
}
    return LineMap.get(line_end);
}
    
}

 

测试用例(将输入输出结果截图提交):

 1、测试第一个线路查询功能:

 

2、测试非换乘站点到非换乘站点

 

 

 

 3、测试换乘站点到换乘站点

 

 

总结

 

首先是对于这次交作业的方式——上传博客感到很新颖,第一次写博客真的不太会。

其次是对于这次作业计算地铁地铁线路最短路径,让我对Dijkstra算法有了更深的了解,本次Dijkstra算法主要参考thankkk的博客。

另外在输出格式上开始也想想thankkk一样使用命令行但不太会用,便借鉴了suppersam的运行方式。

GitHub地址:https://github.com/ChasenSi/Subway

posted @ 2020-11-05 09:40  Doraemon&big  阅读(251)  评论(0)    收藏  举报

Happy everyday!