地铁收费系统 计应193 第二组 杨婷宇
PSP阶段 |
预估时间 |
实际所用时间 |
计划 |
15 |
9 |
|
12 |
8 |
开发 |
55 |
60 |
|
10 |
8 |
|
8 |
10 |
|
10 |
8 |
|
8 |
5 |
|
12 |
15 |
|
20 |
26 |
|
8 |
9 |
|
15 |
12 |
报告 |
18 |
11 |
|
5 |
4 |
|
4 |
2 |
|
6 |
6 |
总共花费时间 |
70 |
75 |
计划:
明确需求和其他相关因素,估计每个阶段的时间成本。
需求分析:
起点站到终点站之间有效最短路径
起始站到终点站两点经过的站点数
具体设计:
用迪杰斯特拉算法实现两个站点之间的最短路径搜索
最终根据最短路径来计算花费
具体代码实现:
创建一个数据构造类,初始化南京地铁的各条线路站点数据。
1 package subway; 2 3 import java.util.ArrayList; 4 import java.util.HashSet; 5 import java.util.List; 6 import java.util.Set; 7 8 /** 9 * desc:构造数据关系(以南京地铁站1\2\3\10号线为例) 10 * @author chaisson 11 * @since 2015-5-31 上午10:23:52 12 * 13 */ 14 public class DataBuilder { 15 16 public static List<Station> line1 = new ArrayList<Station>();//1号线 17 public static List<Station> line2 = new ArrayList<Station>();//2号线 18 public static List<Station> line3 = new ArrayList<Station>();//3号线 19 public static List<Station> line10 = new ArrayList<Station>();//10号线 20 public static List<Station> lineS1 = new ArrayList<Station>();//s1号线 21 public static List<Station> lineS8 = new ArrayList<Station>();//s8号线 22 public static Set<List<Station>> lineSet = new HashSet<List<Station>>();//所有线集合 23 public static int totalStaion = 0;//总的站点数量 24 static { 25 //1号线 26 String line1Str = "迈皋桥站、红山动物园站、南京站、新模范马路站、玄武门站、鼓楼站、珠江路站、新街口站、张府园站、三山街站、中华门站、安德门站、天隆寺站、软件大道站、花神庙站、南京南站、双龙大道站、河定桥站、胜太路站、百家湖站、小龙湾站、竹山路站、天印大道站、龙眠大道站、南医大·江苏经贸学院站、南京交院站、中国药科大学站"; 27 String[] line1Arr = line1Str.split("、"); 28 for(String s : line1Arr){ 29 line1.add(new Station(s)); 30 } 31 for(int i =0;i<line1.size();i++){ 32 if(i<line1.size()-1){ 33 line1.get(i).next = line1.get(i+1); 34 line1.get(i+1).prev = line1.get(i); 35 } 36 } 37 38 /*******************************************************************************/ 39 //2号线 40 String line2Str = "油坊桥站、雨润大街站、元通站、奥体东站、兴隆大街站、集庆门大街站、云锦路站、莫愁湖站、汉中门站、上海路站、新街口站、大行宫站、西安门站、明故宫站、苜蓿园站、下马坊站、孝陵卫站、钟灵街站、马群站、金马路站、仙鹤门站、学则路站、仙林中心站、羊山公园站、南大仙林校区站、经天路站"; 41 String[] line2Arr = line2Str.split("、"); 42 for(String s : line2Arr){ 43 line2.add(new Station(s)); 44 } 45 for(int i =0;i<line2.size();i++){ 46 if(i<line2.size()-1){ 47 line2.get(i).next = line2.get(i+1); 48 line2.get(i+1).prev = line2.get(i); 49 } 50 } 51 52 /*******************************************************************************/ 53 //3号线 54 String line3Str = "林场站、星火路站、东大成贤学院站、泰冯路站、天润城站、柳洲东路站、上元门站、五塘广场站、小市站、南京站、南京林业大学·新庄站、鸡鸣寺站、浮桥站、大行宫站、常府街站、夫子庙站、武定门站、雨花门站、卡子门站、大明路站、明发广场站、南京南站、宏运大道站、胜太西路站、天元西路站、九龙湖站、诚信大道站、东大九龙湖校区站、秣周东路站"; 55 String[] line3Arr = line3Str.split("、"); 56 for(String s : line3Arr){ 57 line3.add(new Station(s)); 58 } 59 for(int i =0;i<line3.size();i++){ 60 if(i<line3.size()-1){ 61 line3.get(i).next = line3.get(i+1); 62 line3.get(i+1).prev = line3.get(i); 63 } 64 } 65 66 /*******************************************************************************/ 67 //10号线 68 String line10Str = "雨山路站、文德路站、龙华路站、南京工业大学站、浦口万汇城站、临江站、江心洲站、绿博园站、梦都大街站、奥体中心站、元通站、中胜站、小行站、安德门站"; 69 String[] line10Arr = line10Str.split("、"); 70 for(String s : line10Arr){ 71 line10.add(new Station(s)); 72 } 73 for(int i =0;i<line10.size();i++){ 74 if(i<line10.size()-1){ 75 line10.get(i).next = line10.get(i+1); 76 line10.get(i+1).prev = line10.get(i); 77 } 78 } 79 80 /*******************************************************************************/ 81 //s1号线 82 String lineS1Str = "南京南站、翠屏山站、河海大学·佛城西路站、吉印大道站、正方中路站、翔宇路北站、翔宇路南站、禄口机场站"; 83 String[] lineS1Arr = lineS1Str.split("、"); 84 for(String s : lineS1Arr){ 85 lineS1.add(new Station(s)); 86 } 87 for(int i =0;i<lineS1.size();i++){ 88 if(i<lineS1.size()-1){ 89 lineS1.get(i).next = lineS1.get(i+1); 90 lineS1.get(i+1).prev = lineS1.get(i); 91 } 92 } 93 94 /*******************************************************************************/ 95 //s8号线 96 String lineS8Str = "泰山新村站、泰冯路站、高新开发区站、信息工程大学站、卸甲甸站、大厂站、葛塘站、长芦站、化工园站、六合开发区站、龙池站、雄州站、凤凰山公园站、方州广场站、沈桥站、八百桥站、金牛湖站"; 97 String[] lineS8Arr = lineS8Str.split("、"); 98 for(String s : lineS8Arr){ 99 lineS8.add(new Station(s)); 100 } 101 for(int i =0;i<lineS8.size();i++){ 102 if(i<lineS8.size()-1){ 103 lineS8.get(i).next = lineS8.get(i+1); 104 lineS8.get(i+1).prev = lineS8.get(i); 105 } 106 } 107 108 lineSet.add(line1); 109 lineSet.add(line2); 110 lineSet.add(line3); 111 lineSet.add(line10); 112 lineSet.add(lineS1); 113 lineSet.add(lineS8); 114 totalStaion = line1.size() + line2.size() + line3.size() + line10.size() + lineS1.size() + lineS8.size(); 115 System.out.println("总的站点数量:"+totalStaion); 116 } 117 }
构建地铁站对象
1 package subway; 2 3 import java.util.HashMap; 4 import java.util.LinkedHashSet; 5 import java.util.Map; 6 7 public class Station { 8 private String name; //地铁站名称,假设具备唯一性 9 10 public Station prev; //本站在lineNo线上面的前一个站 11 12 public Station next; //本站在lineNo线上面的后一个站 13 14 //本站到某一个目标站(key)所经过的所有站集合(value),保持前后顺序 15 private Map<Station,LinkedHashSet<Station>> orderSetMap = new HashMap<Station,LinkedHashSet<Station>>(); 16 17 public Station (String name){ 18 this.name = name; 19 } 20 21 public String getName() { 22 return name; 23 } 24 25 public void setName(String name) { 26 this.name = name; 27 } 28 29 public LinkedHashSet<Station> getAllPassedStations(Station station) { 30 if(orderSetMap.get(station) == null){ 31 LinkedHashSet<Station> set = new LinkedHashSet<Station>(); 32 set.add(this); 33 orderSetMap.put(station, set); 34 } 35 return orderSetMap.get(station); 36 } 37 38 public Map<Station, LinkedHashSet<Station>> getOrderSetMap() { 39 return orderSetMap; 40 } 41 42 @Override 43 public boolean equals(Object obj) { 44 if(this == obj){ 45 return true; 46 } else if(obj instanceof Station){ 47 Station s = (Station) obj; 48 if(s.getName().equals(this.getName())){ 49 return true; 50 } else { 51 return false; 52 } 53 } else { 54 return false; 55 } 56 } 57 58 @Override 59 public int hashCode() { 60 return this.getName().hashCode(); 61 } 62 }
算法
1 package subway; 2 3 import java.util.ArrayList; 4 import java.util.LinkedHashSet; 5 import java.util.List; 6 7 public class Subway { 8 9 private List<Station> outList = new ArrayList<Station>();//记录已经分析过的站点 10 11 //计算从s1站到s2站的最短经过路径 12 public void calculate(Station s1,Station s2){ 13 if(outList.size() == DataBuilder.totalStaion){ 14 System.out.println("找到目标站点:"+s2.getName()+",共经过"+(s1.getAllPassedStations(s2).size()-1)+"站"); 15 for(Station station : s1.getAllPassedStations(s2)){ 16 System.out.print(station.getName()+"->"); 17 } 18 return; 19 } 20 if(!outList.contains(s1)){ 21 outList.add(s1); 22 } 23 //如果起点站的OrderSetMap为空,则第一次用起点站的前后站点初始化之 24 if(s1.getOrderSetMap().isEmpty()){ 25 List<Station> Linkedstations = getAllLinkedStations(s1); 26 for(Station s : Linkedstations){ 27 s1.getAllPassedStations(s).add(s); 28 } 29 } 30 Station parent = getShortestPath(s1);//获取距离起点站s1最近的一个站(有多个的话,随意取一个) 31 if(parent == s2){ 32 System.out.println("找到目标站点:"+s2+",共经过"+(s1.getAllPassedStations(s2).size()-1)+"站"); 33 for(Station station : s1.getAllPassedStations(s2)){ 34 System.out.print(station.getName()+"->"); 35 } 36 return; 37 } 38 for(Station child : getAllLinkedStations(parent)){ 39 if(outList.contains(child)){ 40 continue; 41 } 42 int shortestPath = (s1.getAllPassedStations(parent).size()-1) + 1;//前面这个1表示计算路径需要去除自身站点,后面这个1表示增加了1站距离 43 if(s1.getAllPassedStations(child).contains(child)){ 44 //如果s1已经计算过到此child的经过距离,那么比较出最小的距离 45 if((s1.getAllPassedStations(child).size()-1) > shortestPath){ 46 //重置S1到周围各站的最小路径 47 s1.getAllPassedStations(child).clear(); 48 s1.getAllPassedStations(child).addAll(s1.getAllPassedStations(parent)); 49 s1.getAllPassedStations(child).add(child); 50 } 51 } else { 52 //如果s1还没有计算过到此child的经过距离 53 s1.getAllPassedStations(child).addAll(s1.getAllPassedStations(parent)); 54 s1.getAllPassedStations(child).add(child); 55 } 56 } 57 outList.add(parent); 58 calculate(s1,s2);//重复计算,往外面站点扩展 59 } 60 61 //取参数station到各个站的最短距离,相隔1站,距离为1,依次类推 62 private Station getShortestPath(Station station){ 63 int minPatn = Integer.MAX_VALUE; 64 Station rets = null; 65 for(Station s :station.getOrderSetMap().keySet()){ 66 if(outList.contains(s)){ 67 continue; 68 } 69 LinkedHashSet<Station> set = station.getAllPassedStations(s);//参数station到s所经过的所有站点的集合 70 if(set.size() < minPatn){ 71 minPatn = set.size(); 72 rets = s; 73 } 74 } 75 return rets; 76 } 77 78 //获取参数station直接相连的所有站,包括交叉线上面的站 79 private List<Station> getAllLinkedStations(Station station){ 80 List<Station> linkedStaions = new ArrayList<Station>(); 81 for(List<Station> line : DataBuilder.lineSet){ 82 if(line.contains(station)){//如果某一条线包含了此站,注意由于重写了hashcode方法,只有name相同,即认为是同一个对象 83 Station s = line.get(line.indexOf(station)); 84 if(s.prev != null){ 85 linkedStaions.add(s.prev); 86 } 87 if(s.next != null){ 88 linkedStaions.add(s.next); 89 } 90 } 91 } 92 return linkedStaions; 93 } 94 95 /** 96 * desc: How to use the method 97 * author chaisson 98 * since 2015-5-31 99 * version 1.0 100 */ 101 public static void main(String[] args) { 102 long t1 = System.currentTimeMillis(); 103 Subway sw = new Subway(); 104 sw.calculate(new Station("南京站"), new Station("奥体东站")); 105 long t2 = System.currentTimeMillis(); 106 System.out.println(); 107 System.out.println("耗时:"+(t2-t1)+"ms"); 108 } 109 }
代码复审:
首先使用debug一步一步的检查运行,对出现的错误进行修改
然后将重复的代码抽取成一个方法,减少代码的长度,增加可阅读性
总结:
由于所学知识欠缺,完成的比较仓促,对一些东西不是很清楚,争取下次写的时候有改进,继续努力。