北京地铁出行路径规划

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() + "\r\n");
		            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
在这里插入图片描述

posted @ 2019-10-15 04:56  TutuLei  阅读(356)  评论(0编辑  收藏  举报