地铁路线最短路径需求分析

1.主要功能

功能介绍:

(以北京地铁路线图为例)

1.用户输入起始站与终点站。

2.系统实现计算出两站之间最短的乘车路线,并将将最短路线中的所有站点按要求输出,为用户提供乘车参考。

实现要求:

 

 

 

 

提供一副地铁线路图,计算指定两站之间最短(最少经过站数)乘车路线;输出指定地铁线路的所有站点。以北京地铁为例

如存在多条最短路线,同时输出所有路线。

输出格式如下:

地铁线路总数
线路名1 站名1 站名2 站名3 ...
线路名2 站名1 站名2 站名3 ...
线路名3 站名1 站名2 站名3 ......

2.实现语言

Java

3.实现算法

BFS (地铁路线之间的距离设为相等)

4.职责划分

1.BeanStation类 地铁站的类型

 

public class BeanStation {
    private String stationName;  //站名
    private List<String> lineName; //站所在的线名
    private List<BeanStation> neighborStation; //站的邻居
    
省略get&&set

 


2.BeanLine类 地铁线路的类型

 

public class BeanLine {

    private String lineName; //线名
    private List<BeanStation> stations; //位于线上的站
    
省略get&&set

 

 

3.GetData类 来获取txt中的文件,对station和line进行初始化处理

 

4.Main:主程序 实现最短路径的搜索

5.核心代码

BeanStation:

package ShortRoute.model;

import java.util.ArrayList;
import java.util.List;

public class BeanStation {
    private String stationName;
    private List<String> lineName;
    private List<BeanStation> neighborStation;
    
    public String getStationName() {
        return stationName;
    }
    public void setStationName(String stationName) {
        this.stationName = stationName;
    }
    public List<String> getLineName() {
        return lineName;
    }
    public void setLineName(List<String> lineName) {
        this.lineName = lineName;
    }
    public List<BeanStation> getNeighborStation() {
        return neighborStation;
    }
    public void setNeighborStation(List<BeanStation> neighborStation) {
        this.neighborStation = neighborStation;
    }
    
    
}

 

 

BeanLine:

 

package ShortRoute.model;

import java.util.List;

public class BeanLine {

    private String lineName; //线名
    private List<BeanStation> stations; //线上的站
    
    public String getLineName() {
        return lineName;
    }
    
    public void setLineName(String lineName) {
        this.lineName = lineName;
    }
    
    public List<BeanStation> getStations() {
        return stations;
    }
    
    public void setStations(List<BeanStation> stations) {
        this.stations = stations;
    }
    
    public void add(BeanStation station) {
        this.stations.add(station);
        
    }
    
    
}

 

读入地铁线路信息并初始化站点和线路的信息:

public class GetData {
    
    public static int linenum=0;
    
    public static ArrayList<BeanLine> lineSet = new ArrayList<BeanLine>(); 
    
    public GetData(String path) throws IOException{
        
        File file = new File(path);
        InputStreamReader isr = new InputStreamReader(new FileInputStream(file), "UTF-8");
        BufferedReader br = new BufferedReader(isr);
        //读取数据
        try {
            String in = "";
            while((in=br.readLine())!=null){
                linenum++;
                
                String[] stationPart = in.split(" ");
                BeanLine line = new BeanLine();
                List<BeanStation> stations =new ArrayList<BeanStation>();
                line.setLineName(stationPart[0]);
                //提取线路名、站点
                for(int i = 1;i<stationPart.length;i++)
                {
                    BeanStation station = new BeanStation();
                    List<String> lines = new ArrayList<String>();
                    List<BeanStation> neighborStation = new ArrayList<BeanStation>();
                    
                    station.setStationName(stationPart[i]);
                    if(i==stationPart.length-1 && stationPart[i].equals(stationPart[1]))
                    {
                        continue;//判断是否是否是环路
                    }
                    int ischange=0;
                    int linenum;
                    int stationnum;
                    //是否是换乘站
                    int posline=0,posstation=0;
                    int flag=0;//确定站点是否存在
                    for(int j=0;j<lineSet.size();j++)
                    {
                        for(int k=0;k<lineSet.get(j).getStations().size();k++)
                        {
                            if(stationPart[i].equals(lineSet.get(j).getStations().get(k).getStationName()))
                            {
                                posline=j;
                                posstation=k;
                                station=lineSet.get(j).getStations().get(k);
                                lines=station.getLineName();
                                lines.add(line.getLineName());//加入新的换乘线
                                neighborStation=station.getNeighborStation();
                                flag=1;
                            }
                        }
                    }
                    if(flag==0)//不存在
                    {
                        lines.add(line.getLineName());
                    }
    
                    //加入点信息
                    station.setLineName(lines);            
                    stations.add(station);
                    if(flag==1)
                    {
                        List<BeanStation> updatestations = new ArrayList<BeanStation>();
                        updatestations = lineSet.get(posline).getStations();
                        updatestations.set(posstation, station);
                        lineSet.get(posline).setStations(updatestations);
                    }
                    
                    line.setStations(stations);
                    }
    
                lineSet.add(line);
                }
        }catch (IOException e) {
            e.printStackTrace();
        }
    }

 

将每个站点的邻居加入到每个站点的邻居列表中:

public void getstationinfo(List<BeanLine> lines) {//存放邻居节点
        
        for(int i = 0 ;i<lines.size();i++)
        {
            for(int j=0;j<lines.get(i).getStations().size();j++) {
                List<BeanStation> neighborStation = new ArrayList<BeanStation>();
                if(j>0)
                    neighborStation.add(lines.get(i).getStations().get(j-1));
                if(j<lines.get(i).getStations().size()-1)
                    neighborStation.add(lines.get(i).getStations().get(j+1));
                lines.get(i).getStations().get(j).setNeighborStation(neighborStation);
            }
        }
    }

 

读取文件的入口:

GetData = new GetData("C:\\Users\\xch\\Desktop\\data1.txt");

界面初始化

public static void main(String[] args) throws IOException {
        Scanner input = new Scanner(System.in);
        GetData = new GetData("C:\\Users\\xch\\Desktop\\data1.txt");
        GetData.getstationinfo(GetData.lineSet);
        System.out.println("**********************************");
        System.out.println("**********************************");
        System.out.println("**********************************");
        System.out.println("**                              **");
        System.out.println("**       地铁路线查询系统              **");
        System.out.println("**                              **");
        System.out.println("**********************************");
        System.out.println("**********************************");
        System.out.println("**********************************");
        
        System.out.println("功能选项:1 查看地铁线路     2 查询地铁最短路径");
    
        int op = input.nextInt();
        while(op!=1&&op!=2) {
            System.out.println("没有这个选项,请重新输入!!");
            op = input.nextInt();
        }
        if(op==1) {
            System.out.println("请输入地铁路线名:");
            String roadname = input.next();
            searchRoad(roadname);
        }
        else if(op==2) {
            System.out.print("请输入起点站名:");
            String start = input.next();
            System.out.print("请输入终点站名:");
            String end = input.next();
            getShortRoute(start, end);
        }
        input.close();
    }

查询地铁线路的站点

private static void searchRoad(String roadname) {
        // TODO Auto-generated method stub
        int flag=0;
        for(BeanLine line: LineSet){
            if(line.getLineName().equals(roadname)){
                System.out.print(roadname+  ":");
                for(int j=0;j<line.getStations().size();j++)
                {
                    System.out.print(line.getStations().get(j).getStationName()+" ");
                }
                flag=1;
                break;
            }
        }
        if(flag==0){
            System.out.println("地铁路线不存在");
        }
    }

 

对特殊乘坐地铁情况进行分析

private static BeanStation getStart(String startStation) {
        // TODO Auto-generated method stub
        BeanStation station = new BeanStation();
        for(int i=0;i<GetData.lineSet.size();i++) {
            for(int j=0;j<GetData.lineSet.get(i).getStations().size();j++) {
                if(startStation.equals(GetData.lineSet.get(i).getStations().get(j).getStationName())) {
                    station = GetData.lineSet.get(i).getStations().get(j);
                    return station;
                }
            }
        }
        return null;
    }
    //起点不存在    
        BeanStation startStation = new BeanStation();
        startStation = getStart(startstation);
        if(startStation==null) {
            System.out.println("起点不存在");
        }
        //终点不存在情况
        BeanStation endStation = new BeanStation();
        endStation = getStart(endstation);
        if(endStation==null) {
            System.out.println("终点不存在");
        }
        //终点站与起点站一致
        if(startstation.equals(endStation)) {
            System.out.print("已在该站点,不需要乘坐"+startstation);
        }

 

利用BFS算法建立队列查找地铁路线

private static void getShortRoute(String startStation, String endStation) {
 
        BeanStation startStation1 = new BeanStation();
        startStation1 = getStart(startStation);
        if(startStation==null) {
            System.out.println("起点不存在");
            System.exit(1);
        }
        //终点不存在情况
        BeanStation endStation1 = new BeanStation();
        endStation1 = getStart(endStation);
        if(endStation==null) {
            System.out.println("终点不存在");
            System.exit(1);
        }
        
        if(startStation.equals(endStation)) {
            System.out.print("已在该站点,不需要乘坐");
            System.exit(1);
        }
        Map<String,Integer> map=new HashMap<String, Integer>();//站点距离信息
        Map<String,ArrayList<String>> path=new HashMap<String,ArrayList<String>>();//路径信息
        //存储起点距离信息
        map.put(startStation,0);
        ArrayList<String> a=new ArrayList<String>();
        a.add(startStation);
        path.put(startStation,a);
        //创建队列,把起点加入到队列中
        Queue<String> queue=new LinkedList<String>();
        queue.offer(startStation);
        //当队列不为空
        while(!queue.isEmpty()){
            String top =queue.poll();
            
            //当队列不为空时,在队尾加入队列头的邻居站点
            int dis = map.get(top)+1;
            ArrayList<String> topPath = path.get(top);
            
            for (BeanStation c : StationSet.get(top).getNeighborStation()) {

                //判断是否已经遍历该点
                if (!map.containsKey(c)){//没有遍历 加入队列
                    map.put(c.getStationName(), dis);
                    ArrayList<String> Path = new ArrayList<String>(topPath);
                    Path.add(c.getStationName());
                    path.put(c.getStationName(),Path);
                    queue.add(c.getStationName());
                    //当遍历到达终点站时,输出
                    if(c.equals(endStation)){
                        System.out.println("总共"+dis+"站");
                        getPath(path.get(c));
                        return;
                    }
                }
            } 
        }
    }

 

输出路径函数

public static void getPath(ArrayList<String> path){//路径输出
        System.out.println(getexchangeline(path.get(0),path.get(1)));
        System.out.print(" "+path.get(0)+" ");
        int i;
        //判断换乘
        for(i=0;i<path.size()-2;i++){
            System.out.print(path.get(i+1)+" ");
            if(isExchange(path.get(i),path.get(i+2))){
                System.out.println();
                System.out.println(getexchangeline(path.get(i),path.get(i+1))+" ");
                System.out.println(getexchangeline(path.get(i+1),path.get(i+2)));
                System.out.println(" "+path.get(i+1)+" ");
            }
        }
        System.out.println("->->换乘  "+path.get(i+1)+" ");
        System.out.println(getexchangeline(path.get(i),path.get(i+1)));
    }

 

判断是否换乘的函数和返回换线名函数

//判断是否换乘    
public static boolean isExchange(BeanStation line1,BeanStation line2) {
        int  isExchange = 1;
        for(String ln1 :line1.getLineName()) {
            for(String ln2 :line2.getLineName()) {
                if(ln1.equals(line2)) {
                    isExchange = 0;
                    return false;
                }
            }
        }
        return true;
    }

//换乘的路线名
    public static String getexchangeline(String station1,String station2){
            for(String name:StationSet.get(station1).getLineName()){
                if(StationSet.get(station2).getLineName().contains(name))
                return name;
            }
            return null;
        }

         }

 

 

6.测试用例

1.查看所有地图信息

 

2.查询单条线路信息

 

 

 

 

 

 

3.在同一地铁线上乘坐的测试

 

 

 

4.需要换乘的路线测试

 

 

 

 

 

 

 

 

 

 

 

5.设置不存在起点地铁站测试

 

 

6.设置不存在终点站测试

 

 

 

8.不存在的地铁线路测试

 

 

 

 

 

9.在同一站不需要换乘

 

 

 



 

7.总结

 

 

1.第一次使用博客上写一个项目,熟悉了许多博客的用法,是一次不可多得的机会。

2.新学习了Dijkstra算法,复习了BFS,掌握了算法的运算方式,还学习了一些其他的搜索的算法,

3.在写Java的时候认识到自己还有很多不了解的地方,通过同学和网上的帮助,掌握了一些以前不会的方法,自己还需要在编码能力上加油。

posted @ 2020-10-21 11:21  好多鱼鱼鱼  阅读(221)  评论(0)    收藏  举报