github:https://github.com/dozoroy/subway
一、任务:
实现一个帮助进行北京地铁出行路线规划的命令行程序,能处理正确输入的命令行的计算地铁线路最短路径(乘坐最少站数)。
二、设计:
输入格式:选择.txt格式来输入,方便快捷。
需求1:显示地铁线路信息
将北京地铁线路信息等用一个文本文件以 subway.txt的形式保存起来,保存的信息包括地铁线路名称和拥有的站数、对应线路下的站点名称以及相邻站的距离(根据最后求最少站数的需求,所有相邻站数的距离都设置为1,终点站设为-1),使得可以通过读取这个文件,就能获取关于北京地铁线路的所有信息来进行后续操作。
java subway -map subway.txt
subway.txt的部分截图
map代码实现:
private void fileReader(){ File f = new File("maptxt/subway.txt"); if(f.exists()){ try { FileReader out = new FileReader(f); BufferedReader br = new BufferedReader(out); String line = null; int nums = Integer.parseInt(br.readLine()); for(int i = 0;i < nums;i++){ br.readLine(); String trackInfo = br.readLine(); String[] track = trackInfo.split("[\\s]"); String trackName = track[0]; int trackStationsNum = Integer.parseInt(track[1]); str[i][0]=trackName; String[] station; String stationName; int nextDistance; Station head = null; Station preSta = null; Edge pre = null; Station s; for (int j = 0; j < trackStationsNum; j++) { line = br.readLine(); station = line.split("[\\s]"); stationName = station[0]; nextDistance = Integer.parseInt(station[1]); s = new Station(stationName); s.trackname = trackName; str[i][j+1] = stationName; if(!map.containsKey(s)){ map.put(s, new ArrayList()); }else{ for (Station sta : map.keySet()) { if(s.stationName.equals(sta.stationName)){ s = sta; break; } } } if(pre != null) map.get(s).add(pre); if(preSta != null) map.get(preSta).add(new Edge(s,trackName,pre.distance)); preSta = s; pre = new Edge(s,trackName, nextDistance); if(j == 0){ head = s; } if(j == trackStationsNum-1 && nextDistance > 0){ map.get(head).add(pre); map.get(s).add(new Edge(head,trackName,nextDistance)); } } } br.close(); out.close(); } catch (Exception e) { e.printStackTrace(); } } }
需求2:查询指定路线经过的站点
查询指定地铁线经过的站点,程序就需要能够从线路的起始站点开始,依次输出该地铁线经过的所有站点,直到终点站。
java subway -a line -map subway.txt -o station.txt
输入“-a”后,再输入" 1号线 "和“ 2号线 ”的输出截图:
输入错误线路名称"sdad"后的输出截图:
函数代码实现:
public void ShowStation(String stationname) { int index = 0; int flag = 0; for(int i = 0; i < str.length; i++){ if(str[i][0]!=null){ if(str[i][0].equals(stationname)){ index = i; flag = 1; break; } } } if (flag == 1 ) { for (int j = 1; j < str.length; j++) { if(str[index][j]==null) break; if( j == 1) System.out.print( str[index][1]); else System.out.print( " -> " + str[index][j]); } } else if (flag == 0){ System.out.println("不存在该线路"); } }
需求3:找出两个地铁站间最短路径(最少的站数)以及相应的换乘信息
计算从出发到目的站点之间的最短(经过的站点数最少)路线,并输出经过的站点的个数和路径(包括出发与目的站点),需要换乘则在换乘站的下一行输出换乘的线路。
subway.exe -b start end -map subway.txt -o routine.txt
起点不存在或终点不存在的输入的截图:
1.输入起点不存在的“a”
2.输入终点不存在的“b”
3.输入起点与终点相同
4.没有换乘的情况下,输入“-b”后,再输入起点(苹果园)和终点(五棵松)的截图:
5.有换乘的情况下,输入“-b”后,再输入起点(大红门)和终点(达官营)的截图:
函数代码实现:
private void dijkstraTravel(Station s){ Setset = map.keySet(); for (Station station : set) { station.visited = false; station.dist = Integer.MAX_VALUE; } s.dist = 0; boolean flag = true; while(flag){ Station v = null; Station w; for (Station station : map.keySet()) { if(station.visited == true) continue; if(v == null || station.dist < v.dist) v = station; } v.visited = true; List list = map.get(v); for (int i = 0; i < list.size(); i++) { w = list.get(i).station; if(!w.visited){ int d = list.get(i).distance; if(v.dist + d < w.dist){ w.dist = v.dist + d; w.path = v; } } }
三、思路:
语言选择较为熟悉的java,使用邻接表的方式存储subway.txt,把北京的地铁看成是有权无向图,采用Dijkstra算法,遍历所有节点找到未访问过的节点中累积权值,最小的设为a,遍历该节点所有可达边(连通到目标节点B),如果节点A累积权值加可达边权值小于目标节点B自身的累积权值,则对目标节点B进行更新,将节点A设定为已访问,重复直到所有节点均访问完毕。
四、总结:
这次的北京地铁作业让我明白了好好学习数据结构的重要性,一些常用的算法我也应该掌握运用得更加地熟练灵活。鉴于本次的实验,我对完成程序功能时应该如何设计结构有了初步的体验心得,对于程序的基本异常处理有了次尝试。总而言之,这个学期的软件工程基础课要多多加油和努力。
五、测试计算:
1.对比估计开发时间与实际时间
2.模块接口的设计与实现过程
3.模块部分单元测试展示
4.模块部分异常处理说明
5.自我测试,修改代码,提交修改,事后总结。