Metro Line project learning record

Metro Line project learning record

github Address: https://github.com/zky320/Subway

 


 

Use the command-line statement

1. Get custom metro corresponding file (named subway.txt)

java -cp .:* subway -map subway.txt

2. Get all the sites specify the name of the railway line and into the named file

java -cp .:* subway -a 1号线 -map subway.txt -o station.txt

Output file formats:

Line 1: 
?????? 
Honghuli 
west station (line 6 can be transferred) 
in the northwest corner 
······

3. Get the shortest path starting point and the terminal and into the named file

java -cp:. * subway -b Honghuli Fuxing Road -map subway.txt -o routine.txt

Output file formats:

3         
Honghuli 
West Station 
Line 6 
Fuxing Road

Tips: java jar files need to call the package, command line format java -cp:. A.jar B, while java -cp:. * Subway can call all the jar packages in the current folder.

 


 

Test (shortest path): Examples

1. On the (head) on the same line, without any transfer site: Liu Yuan, Honghuli

2. On the (tail) on the same line, without any transfer site: Civic Plaza, East China Sea Road

3. In the middle of the same line, without any transfer sites: North bamboo, Xinkaihe

4. The start and end points are transfected site (in the same line): West Point, the tile

The start and end points are transferred station (not in the same line): West Point, Zhangxingzhuang

6. The starting point for the transfer station, the end of non-GM site: West Point, One Bridge

7. The starting point for non-GM site and finish at the transfer station (halfway including reverse): Lee House, Zhigu

8. start and end points are non-GM site: Tiantai Road, Heping Road

9.5 Line and 6- Line special overlap, both start and end at the 5 Line and 6 Hao online: Tumor Hospital, Cultural Center

10.5 Line and 6. Line special overlap, do not start and end at the 5 Line and 6 No. online, but via (transfer station does not occur): Southwest floor, sports centers

11.  5 Line and 6- Line special overlap, do not start and end in May Line and 6 Hao online, but via (transfer occurs station): Southwest House, Water Park East

 


 

Part of the error

1. Command Error

2. Customize the subway file errors

3. No designated subway line

4. The same start and end points

5. trivial input error or command error

 

 

 


 

Code

Using a programming language: the Java

1. Read the corresponding custom file:

Custom file formats:

6    ->地铁线路数
15    ->转站数
1 23    ->地铁线路名  该地铁线路含有多少站点
刘园 0    ->站点名  转站(不转站为0,转站则为转站的地铁线路名)
西横堤 0
果酒厂 0
本溪路 0
勤俭道 0
洪湖里 0
西站 6
······

【一开始为三元组(地铁线路名,地铁站名,转站线路号),开始写代码的时候发现这样的格式存储起来不太方便,改成了二元组(地铁站名,转站线路号)】

存储数据方式:Json对象+Json数组 

{
"1号线": [
{ "siteName":"刘园" , "transfer":"0" },
{ "siteName":"西横堤" , "transfer":"0" },
{ "siteName":"果酒厂" , "transfer":"0" },
  ........
]
}
{
"2号线": [
{ "siteName":"曹庄" , "transfer":"0" },
{ "siteName":"卞兴" , "transfer":"0" },
{ "siteName":"芥园西道" , "transfer":"0" },
  ........
]
}
{
  ........
}

读取文件并存储数据代码如下:

 1 public static void readtxt(String txt){
 2         int mark=0;
 3         int nn=0;   //用于添加subwayN,用于后期读取JsonArray来创建图
 4         int subwaynum=0;
 5         int subwaysum=0;
 6         JSONArray jArr = null;
 7         String txtname = txt;
 8 
 9         try (FileReader reader = new FileReader(txtname);
10              BufferedReader br = new BufferedReader(reader) // 建立一个对象,它把文件内容转成计算机能读懂的语言
11         ) {
12             String line;
13             while ((line = br.readLine()) != null) {
14                 String[] str=line.split(" ");
15                 Pattern pattern = Pattern.compile("^[-\\+]?[\\d]*$");
16                 if(str.length==1&&mark==0){  //说明是第一行,记录地铁线路有几条
17                     num=Integer.valueOf(str[0]);
18                     subwayN=new String[num];    //将几号线的名字都存起来
19                     mark++;
20 //                    System.out.println(num);
21                 }
22                 else if(str.length==1&&mark!=0){
23                     trannum=Integer.valueOf(str[0]);
24 //                    System.out.println(trannum);
25                 }
26                 else if(pattern.matcher(str[0]).matches()&&pattern.matcher(str[1]).matches()){  //说明是描述线路的两个数字
27                     subwaynum=Integer.valueOf(str[0]);
28                     subwaysum=Integer.valueOf(str[1]);
29                     subwayN[nn++]=str[0]+"号线";
30                     jArr = new JSONArray();
31 //                    System.out.println(subwaynum+" "+subwaysum);
32                 }
33                 else {  //正常站点名称
34                     JSONObject jobj = new JSONObject();
35                     try {
36                         jobj.put("siteName", str[0]);
37                         jobj.put("transfer", str[1]);
38 
39                     } catch (JSONException e) {
40                         e.printStackTrace();
41                     }
42                     jArr.add(jobj);
43                     flag++;
44                     if(flag==subwaysum){
45                         all.put(subwaynum+"号线",jArr);
46                         flag=0;
47                     }
48                 }
49             }
50             if(flag==num){
51                 all.put(subwaynum+"号线",jArr);
52             }
53 //            System.out.println(all);
54 //            System.out.println(all.getJSONArray("1号线").getJSONObject(0).getString("siteName"));
55         } catch (IOException e) {
56             e.printStackTrace();
57         }
58     }

 

2. 输出地铁线路所有地铁站名称:

  将Json对应对象中的数组读出,并全部输出,代码如下:

 1 public static void writeallstation(String subwaynum,String txt) {
 2         JSONArray Jarray = all.getJSONArray(subwaynum);
 3         try {
 4             File writeName = new File(txt); // 相对路径,如果没有则要建立一个新的output.txt文件
 5             writeName.createNewFile(); // 创建新文件,有同名的文件的话直接覆盖
 6             try (FileWriter writer = new FileWriter(writeName);
 7                  BufferedWriter out = new BufferedWriter(writer)
 8             ) {
 9                 out.write(subwaynum+":\n");
10                 for(int i=0;i<Jarray.size();i++){
11 //                    System.out.print(Jarray.getJSONObject(i).getString("siteName"));
12                     out.write(Jarray.getJSONObject(i).getString("siteName"));
13                     String num=Jarray.getJSONObject(i).getString("transfer");
14                     if(!num.equals("0")){
15                         if(num.length()==1){
16 //                            System.out.println("(可转"+num+"号线)");
17                             out.write("(可转"+num+"号线)\n");
18                         }
19                         else{
20 //                            System.out.println("(可转"+num.charAt(0)+"号线和"+num.charAt(1)+"号线)");
21                             out.write("(可转"+num.charAt(0)+"号线和"+num.charAt(1)+"号线)\n");
22                         }
23                     }
24                     else{
25 //                        System.out.println();
26                         out.write("\n");
27                     }
28                 }
29                 out.flush(); // 把缓存区内容压入文件
30             }
31         } catch (IOException e) {
32             e.printStackTrace();
33         }
34     }

 

3.  输出最短路径:

  将转站节点(一共15个)连接成图,之后将起点站和终点站加入图中,中途出现各种特殊情况,需要将加入点连入图中后删除原本已有的另一条边。在建立图的过程中,一一记录节点在图中的序号,连成完整的无向图后使用 Dijstra 算法取其最短路径。在输出起点到终点的地铁路线时,需要输出转站情况,所以再这之前,将各条地铁线路上包含的图中节点(在图中的序号)进行了记录,当判断改站为转站点时,需检查改点与下一个节点同时出现在哪一条地铁线路中,若改号线路与当前不是同一条,则输出转站情况。

  建图过程中做了数据记录以参照

【 过程中本来想换成将所有站点(一共141个)连成图,之后直接使用 Dijstra 算法取其最短路径。但转念一想觉得原理相同,最终还是选择了原本的方法,写到后期有点后悔,因为各种繁琐 

 最短路径 Dijstra 算法代码如下:

 1 public static String dijkstra(int start, int end) {
 2         // 初始化,第一个顶点求出
 3         int n=record.size();
 4         final int M = Integer.MAX_VALUE;
 5         int[] shortest = new int[n];  //存放从start到其他节点的最短路径
 6         boolean[] visited = new boolean[n]; //标记当前该顶点的最短路径是否已经求出,true表示已经求出
 7         shortest[start] = 0;
 8         visited[start] = true;
 9 
10         //存放从start到其他各节点的最短路径
11         String[] path = new String[n];
12         for(int i = 0; i < n; i++){
13             path[i] = new String(start + "->" + i);
14         }
15         for(int count = 0; count != n-1; count ++){
16             //选出一个距离初始顶点最近的为标记顶点
17             int k = M;
18             int min = M;
19             for(int i =0; i< n ; i++){//遍历每一个顶点
20                 if( !visited[i] && graph[start][i] != M){ //如果该顶点未被遍历过且与start相连
21                     if(min == -1 || min > graph[start][i]){ //找到与start最近的点
22                         min = graph[start][i];
23                         k = i;
24                     }
25                 }
26             }
27             //正确的图生成的矩阵不可能出现K== M的情况
28             if(k == M) {
29                 System.out.println("the input map matrix is wrong!");
30                 return null;
31             }
32             shortest[k] = min;
33             visited[k] = true;
34             //以k为中心点,更新start到未访问点的距离
35             for (int i = 0; i < n; i++) {
36                 if (!visited[i] && graph[k][i] != M) {
37                     int callen = min + graph[k][i];
38                     if (graph[start][i] == M || graph[start][i] > callen) {
39                         graph[start][i] = callen;
40                         path[i] = path[k] + "->" + i;
41                     }
42                 }
43             }
44         }
45 
46 //        System.out.println("从"+start+"出发到"+end+"的最短路径为:"+path[end]);
47 
48         return path[end];
49     }

 

总结

  总体来说,顺利完成要求,但方法很繁琐,主要还是开始时考虑得不到位,写到中途又不愿意放弃前期花进去的时间。就当是一次教训,以后还是以此为戒。

 

Guess you like

Origin www.cnblogs.com/zky0320/p/11637614.html