北京地铁规划项目总结

一、项目介绍

  GitHub链接:https://github.com/Magazinediver/Subway

  核心算法:Dijkstra算法

  编写语言:Java

  需求分析:

    1.subway.txt导入地铁线路信息,routine.txt输出地铁线路信息

    2.对地铁行程规划(最短路径查询),并输出

    3.输出地铁信息 1线路信息2站点信息

  北京地铁规划项目总结_第1张图片

 

 

 

二、文件导入方式设计

  2.1导入文本txt格式

24                         //线路总数

1                           //线路编号
23                         //线路中站点数目
一号线                    //线路名
一号线 苹果园 否       //格式: 线路名 站点名 是否换乘,若换乘则列出站点名
一号线 古城 否
一号线 八角游乐园 否
一号线 八宝山 否
一号线 玉泉路 否
一号线 五棵松 否
一号线 万寿路 否
一号线 公主坟 十号线
一号线 军事博物馆 九号线
一号线 木樨地 否
一号线 南礼士路 否
一号线 复兴门 二号线
一号线 西单 四号线
......
 

 

       2.2 java文件导入设计

    1.导入时先按照文档中第一个数字,即线路总数x,建立for循环,获取有x条线路的line_list

    2.再按照每条线路的第一行的数字,获取线路id

    3.利用每条线路中的第二行,取得每条线路中的站点总数y,建立for循环,获取有y个站点的station_list,即每条线路中的站点列表

    4.利用每条线路中的第三行,取得每条线路中的站点中文名称

    5.后面即是地铁站点的输入格式:线路名 站点名 是否换乘,若换乘则列出站点名

       其中先按空格分开一行,存入String s[] ,s[0]所属线路,s[1]站点名,s[2]是否有换乘,若S[2]不是“否“(非换乘站),就将S[2]按照“,”分离,存入String s1[],即trans_list

   2.3java文件导入概念图

    北京地铁规划项目总结_第2张图片

 

 

 

   2.4java文件导入代码实现

      

 while((str=bufferedReader.readLine())!=null) {
         if(str.equals(String.valueOf(j)))//
         {
                Line a  = new Line();
                int k = Integer.parseInt(bufferedReader.readLine());//
                a.setLname(bufferedReader.readLine());
                for(int h=0;h)
                {
                       Station b = new Station();
                       if((str1=bufferedReader.readLine())!=null)
                       {
                              String[] s = str1.split(" ");                                   
                              b.setLine(s[0]);
                              b.setSname(s[1]);
                              if(!s[2].equals("否"))
                              {
                                     String[] s1 = s[2].split(",");
                                     b.setStationrans(s1);
                                     u=0;
                                     for(int p=0;p)
                                     {
                                           if(kb[p].equals(b.getSname()))
                                           {
                                                  u=1;
                                           }
                                     }
                                     if(u!=1) {
                                           kb[t] = b.getSname();
                                           t++;
                                     }
                              }
                       }
                       a.setStation(b);
                }
                list.add(a);
                j++;
        }
        
        return list;
}

 

三、存储结构设计

 

  3.1.无向图站点结构设计

    1.station作为node

    2.每个node之间有边连接,默认权值99,若是两站链接则权值设为1

    3.可获得node再无向图中的序号

    4.可对图中node计数

    5.设计无向图的邻接矩阵结构

public static List mainlist = new ArrayList();  //线路list
protected int[][] subTrainMatrix;                                       // 邻接矩阵
private static final int MAX_WEIGHT = 99;                         // 初始各node间距离99
private int[] dist;                                                             //node间距离存储数组
private List vertex = new ArrayList();  // node
private List edges;                                               //node间距离结构

//各个方法
public int[][] getSubTrainMatrix()                                     //get邻接矩阵
public void setVertex(List vertices)                    //set node
public List getVertex()                                      //get node
public List getEdges()                                          //get边
public int getVertexSize()                                                //图中node数
public int vertexCount()                                                  //node编号
public String toString() 
public subway(int size)
public subway(List vertices)

 

       3.2无向图边结构设计

             

 class Edge {
         private T start, dest;                        //起始站,目标站
         private int weight;                         //边权值
         public Edge()                              
         public Edge(T start, T dest, int weight)
         public String toString()
}

 

       3.3站点结构

              

public class Station {
          public String sname;                     //站点名
          String[] trans = new String[3];             //换乘线路存储数组
          public String line;                       //所属线路名
 
          public void setSname(String sname)       //set站点名
          public String[] getStationrans()            //get站点换乘线路列表
          public void setStationrans(String[] trans)    //set站点换乘线路列表
          public String getLine()                   //get所属线路名
          public void setLine(String line)            //set所属线路名
          public String getSname()                //get所属站点名
}

 

       3.4线路结构

             

 public class Line {
          public String lname;                     //线路名
          public List station = new ArrayList();//站点列表
      
          public List getStation()          //get站点列表
          public void setStation(Station station)      //set站点列表
          public String getLname()                 //get线路名
          public void setLname(String lname)        //set站点名
}

 

四、线路及线路站点输出设计

  4.1站点输出要求

    1.能显示站点所属线路 

    2.能体现出换乘

    3.能体现路线所经过的站点数

 

public static void printstation()//站点输出
{
    for(int i=0;i 
 

 

  4.2输入输出设计

    4.2.1输入设计

    输入格式

      1.获取地铁线路信息      

java subway -map subway.txt

      2.输出地铁特定线路信息 

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

      3.输出地铁线路规划信息

java subway.subway -b 古城 T2航站楼 -map subway.txt -o routine.txt

      4.输入读取代码

         -map 参数来获得对应的自定义地铁文件

         -a 指定了用户希望查询的地铁线路

         -o 指定输出文件

         -b 指定出发站与目标站

if(args.length==0) System.out.println("");
    for(int i=0;i) {
     if(args[i].equals("-map")) {
        flag1=1;
        flag2=1;
     if(args.length) {
            System.out.println("");
        return;
    }
       mainlist =Input.getFileContext(args[i+1]);
    }else if(args[i].equals("-a")) {
        flag1=1;
        operate="-a";
    if(args.length) {
        System.out.println("格式不正确");
        return;
    }
        route=args[i+1];
    }else if(args[i].equals("-b")) {
        flag1=1;
        operate="-b";
        if(args.length) {
            System.out.println("格式不正确");
            return;
        }
        start=args[i+1];
        stop=args[i+2];
    }else if(args[i].equals("-o")) {
        flag1=1;
        output=args[i+1];
        }
    }
    if(flag1==0) {
        System.out.println("格式不正确");
        return;
    }
    else if(flag2==0) {
        System.out.println("格式不正确");
        return;
    }
    if(operate==null&&output!=null) {
        System.out.println("没有输出");
        return;
    }
    else if(operate!=null&&output!=null) {
        if(operate.equals("-a")) {
            try {
                if(outPutRoute(route, output)==false) {
                    System.out.println("没有输出,没有此线路");
                    return;
                }
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }else if(operate.equals("-b")) {
            if(start.equals(stop)) {
                System.out.println("出发站与到达站不能相同!!!!!");
                    return;
                }
                if(Mainoutput(start, stop, output)==false) {
                    System.out.println("没有输出,无法到达");
                    return;
                }
            }
        }        
    }                

 

    4.2.2输出设计

    输出中的站点会携带所属线路

    两个站点间会用->连接

    最后会输出经过的站点数

    控制台中输出

         北京地铁规划项目总结_第3张图片

 

 

              文件输出设计

         

 

五、测试及遇到的问题与解决方法

  5.1输入上的问题

    1.出发站与到达站相同  

    

if(start.equals(stop)) {
                System.out.println("出发站与到达站不能相同!!!!!");
                    return;
                }
                if(Mainoutput(start, stop, output)==false) {
                    System.out.println("没有输出,无法到达");
                    return;
                }
            }

 

    输出:出发站与到达站不可以相同!

    2.出发站或到达站不存在或者线路不存在

    

if(outPutRoute(route, output)==false) {
       System.out.println("没有输出,没有此线路");
       return;
}

 

    3.出发站与到达站之间不可到达

if(Mainoutput(start, stop, output)==false) {
        System.out.println("没有输出,无法到达");
        return;
}

 

    4.没有所需的命令参数或输入格式错误

 

 
  
if(args.length==0) System.out.println("");
    for(int i=0;i) {
     if(args[i].equals("-map")) {
        flag1=1;
        flag2=1;
     if(args.length) { System.out.println(""); return; } mainlist =Input.getFileContext(args[i+1]); }else if(args[i].equals("-a")) { flag1=1; operate="-a"; if(args.length) { System.out.println("格式不正确"); return; } route=args[i+1]; }else if(args[i].equals("-b")) { flag1=1; operate="-b"; if(args.length) { System.out.println("格式不正确"); return; } start=args[i+1]; stop=args[i+2]; }else if(args[i].equals("-o")) { flag1=1; output=args[i+1]; } } if(flag1==0) { System.out.println("格式不正确"); return; } else if(flag2==0) { System.out.println("格式不正确"); return; } if(operate==null&&output!=null) { System.out.println("没有输出"); return; } else if(operate!=null&&output!=null) { ...... } 
 

  在用if进行条件筛选,若是没有参数则会输出:格式不正确

  5.2遇到的问题

    1.在cmd中运行文件始终无法找到主类,显示无法加载

     原因:java文件在cmd中运行必须在bin目录进行带包运行

    2.在cmd中运行报错,在eclipse中确成功运行

       报错1:数组越界

       原因1:因为cmd中的编码类型为gbk(936),而我的代码是utf-8(65001),所以if无法识别,for循环无法停止,导致数组越绝

          报错2:显示乱码

       原因2: 编码类型不同,识别不了,乱码

    3.以为在eclipse中无法带参数运行,造成了很多困扰

          解决办法:eclipse中run configuration...

           北京地铁规划项目总结_第4张图片

 

              4.站点重复输出

      原因:因为换乘站在多条线路中都存在,导致无向图中站点重复

      解决方法:在输入时,对换乘站去重,进行筛选,若是换乘站,只在图中插入一次

      

for(int j=0;j)
            {    
                flag=0;
                Station st = new Station();
                st.setSname("0");
                
                for(int l=0;l//非换乘站
                {
                    if(mainlist.get(i).getStation().get(j).getSname().equals(kb1[l]))
                    {
                        flag = 1;
                    }
                    
                }
                if(flag==0)//是换乘站
                {
                    st.setSname(mainlist.get(i).getStation().get(j).getSname());
                    st.setLine(mainlist.get(i).getStation().get(j).getLine());
                    st.setStationrans(mainlist.get(i).getStation().get(j).getStationrans());
                    c++;
                }
                else{
                    for(int p=0;p)
                    {
                        if((mainlist.get(i).getStation().get(j).getSname().equals(kb1[p]))&&(!(kb[p].equals("0"))))
                        {
                            st.setSname(mainlist.get(i).getStation().get(j).getSname());
                            st.setLine(mainlist.get(i).getStation().get(j).getLine());
                            st.setStationrans(mainlist.get(i).getStation().get(j).getStationrans());
                            kb[p]="0";
                            v++;
                        }
                    
                    }
                }
                    
                
                
                if(!st.getSname().equals("0"))
                {
                    vertices.add(st);
                }
            }

    5.邻接矩阵乱码,无法取得站点在list中编号

      原因:原先我写的demo中node时string类型,可使用indexof(),后来node替换成station类型,导致系统自带函数失效

      解决办法:用自己写的代码替换

      

public int getPosInvertex(Station start) {
        for(int i=0;i)
        {
            //System.out.println(vertex.get(i).getSname());
                if(vertex.get(i).getSname().equals(start.sname))
                {
                    return i;
                }
        }
        //return vertex.indexOf(start);
        return -1;
    }

 

      

 

你可能感兴趣的:(北京地铁规划项目总结)