地铁收费系统 计应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一步一步的检查运行,对出现的错误进行修改

然后将重复的代码抽取成一个方法,减少代码的长度,增加可阅读性

总结:

由于所学知识欠缺,完成的比较仓促,对一些东西不是很清楚,争取下次写的时候有改进,继续努力。

posted @ 2021-04-10 20:42  草莓曲奇饼  阅读(94)  评论(0编辑  收藏  举报