地铁路线最短路径需求分析
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:主程序 实现最短路径的搜索
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.测试用例
2.查询单条线路信息


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

4.需要换乘的路线测试



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

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

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

9.在同一站不需要换乘

7.总结
1.第一次使用博客上写一个项目,熟悉了许多博客的用法,是一次不可多得的机会。
2.新学习了Dijkstra算法,复习了BFS,掌握了算法的运算方式,还学习了一些其他的搜索的算法,
3.在写Java的时候认识到自己还有很多不了解的地方,通过同学和网上的帮助,掌握了一些以前不会的方法,自己还需要在编码能力上加油。


浙公网安备 33010602011771号