编程语言
首页 > 编程语言> > 结对编程-汪虹余 & 郑宏

结对编程-汪虹余 & 郑宏

作者:互联网

[结对编程作业--天津地铁线路]

一、任务:

实现一个帮助进行地铁出行路线规划的命令行程序。

二、设计信息

三、需求分析及实现

  需要实现一个支持自动加载subway.txt 文件的程序,程序启动时需要通过读取 -map 参数来获得对应的自定义地铁文件(命名为 subway.txt),从而得到地铁线路图的信息。一个调用应用程序的示例如下:

java subway -map subway.txt

 

如果用户希望坐地铁,他希望能通过最少的站数从出发点到达目的地,这样就可以在命令行中以 -b 参数加两个地铁站点名称分别作为出发与目的,比如用户希望知道 洪湖里 到复兴路 之间的最短路线是怎样的,他就可以使用如下命令让程序将结果写入 routine.txt 中。

subway.exe -b 洪湖里 复兴路 -map subway.txt -o routine.txt

程序将计算从出发到目的站点之间的最短(经过的站点数最少)路线,并输出经过的站点的个数和路径(包括出发与目的站点)。如果需要换乘,会在换乘站的下一行输出换乘的线路。输出的文件使用-o参数来指定。

一个调用应用程序的示例如下:

java subway -b 华苑 乐园道 -map subway.txt -o routine.txt

下为实际输出的routine.txt 文件的内容  

复制代码

起始站:华苑
3号线
王顶堤
红旗南路
6号线
迎风道
南翠屏
水上公园东路
肿瘤医院
天津宾馆
文化中心
乐园道

共经过 10 站

复制代码

四、逻辑实现

复制代码

1:1号线:刘园,西横堤,果酒厂,本溪路,勤俭道,洪湖里,西站,西北角,西南角,二纬路,海光寺,鞍山道,营口道,小白楼,下瓦房,南楼,土城,陈塘庄,复兴门,华山里,财经大学,双林,李楼
2:2号线:曹庄,卞兴,芥园西道,咸阳路,长虹公园,广开四马路,西南角,鼓楼,东南角,建国道,天津站,远洋国际中心,顺驰桥,靖江路,翠阜新村,屿东城,登州路,国山路,空港经济区,滨海国际机场
3:3号线:小淀,丰产河,华北集团,天士力,宜兴埠,张兴庄,铁东路,北站,中山路,金狮桥,天津站,津湾广场,和平路,营口道,西康路,吴家窑,天塔,周邓纪念馆,红旗南路,王顶堤,华苑,大学城,高新区,学府工业区,杨伍庄,南站
4:5号线:北辰科技园北,丹河北道,北辰道,职业大学,淮河道,辽河北道,宜兴埠北,张兴庄,志成路,思源道,建昌道,金钟河大桥,月牙河,幸福公园,靖江路,成林道,津塘路,直沽,下瓦房,西南楼,文化中心,天津宾馆,肿瘤医院,体育中心,凌宾路,昌凌路,中医一附院,李七庄南
5:6号线:南孙庄,南何庄,大毕庄,金钟街,徐庄子,金钟河大桥,民权门,北宁公园,北站,新开河,外院附中,天泰路,北运河,北竹林,西站,复兴路,人民医院,长虹公园,宜宾道,鞍山西道,天拖,一中心医院,红旗南路,迎风道,南翠屏,水上公园东路,肿瘤医院,天津宾馆,文化中心,乐园道,尖山路,黑牛城道,梅江道,左江道,梅江公园,梅江会展中心,解放南路,洞庭路,梅林路
6:9号线:天津站,大王庄,十一经路,直沽,东兴路,中山门,一号桥,二号桥,张贵庄,新立,东丽开发区,小东庄,军粮城,钢管公司,胡家园,塘沽,泰达,市民广场,太湖路,会展中心,东海路

复制代码

  public void loadLineFile()

// 加载地铁线路数据
    public void loadLineFile(String strSubwayFileName) {
        File fSubway = new File(strSubwayFileName);
        BufferedReader reader = null;

        try {
            InputStreamReader isr = new InputStreamReader(new FileInputStream(strSubwayFileName), "UTF-8");
            reader = new BufferedReader(isr);
            String tempString = null;

            while ((tempString = reader.readLine()) != null) {
                if (tempString.startsWith("\uFEFF")) {
                    tempString = tempString.substring(1, tempString.length());
                }
                listSubwayInfo.addElement(tempString);
            }
            System.out.println("成功加载地铁线路文件!\n");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        parseSubwayStationsData();
    }

  void parseSubwayStationsData()

  void parseSubwayLineData()

 // 地铁数据处理
    void parseSubwayStationsData() {
        for (String strSubwayLine: listSubwayInfo) {
            parseSubwayLineData(strSubwayLine);
        }
    }

    void parseSubwayLineData(String strSubwayLine) {

        String[] arrLineAndStations = strSubwayLine.split(":");     // 划分地铁线路和该线路所有站点
        if (arrLineAndStations.length != 3) {
            System.out.println("地铁数据错误" + strSubwayLine);
            return;
        }
        
        int nLine = getLineNumber(arrLineAndStations[0]);
        stationInfo.put(nLine,arrLineAndStations[1]);
        NtostationInfo.put(arrLineAndStations[1],nLine);
        if (nLine == -1) {
            System.out.println("地铁线路号数据错误" + strSubwayLine);
        }
        String[] arrStrStationNames = arrLineAndStations[2].split(",");
        if(arrStrStationNames[0].equals(arrStrStationNames[arrStrStationNames.length-1]))
        {
            
            for (int i=0; i < arrStrStationNames.length-1; i++) {
                
                String strStationName = arrStrStationNames[i];
                int nStationId = -(nLine*1000 + i+1);
                circleInfo.put(nLine,arrStrStationNames.length-1 );
                Station station = new Station();
                station.stationName = strStationName;
                station.setStationId.add(nStationId);
                mapStationIdtoStation.put(nStationId, station);
                if (!mapNametoStation.containsKey(strStationName)) {
                    mapNametoStation.put(strStationName, station);
                } else {
                    // 如果站点名字存在,证明是中转站
                    Station stationExistedTransferStation = mapNametoStation.get(strStationName);
                    stationExistedTransferStation.setStationId.add(nStationId);
                    mapTransferStationNametoDistance.put(stationExistedTransferStation.stationName, nMaxDistance);
                }
            }
        }
        for (int i=0; i < arrStrStationNames.length; i++) {
            String strStationName = arrStrStationNames[i];
            int nStationId = nLine*1000 + i+1;
            Station station = new Station();
            station.stationName = strStationName;
            station.setStationId.add(nStationId);
            mapStationIdtoStation.put(nStationId, station);
            if (!mapNametoStation.containsKey(strStationName)) {
                mapNametoStation.put(strStationName, station);
            } else {
                // 如果站点名字存在,证明是中转站
                Station stationExistedTransferStation = mapNametoStation.get(strStationName);
                stationExistedTransferStation.setStationId.add(nStationId);
                mapTransferStationNametoDistance.put(stationExistedTransferStation.stationName, nMaxDistance);
            }
        }
    }

迪杰斯特拉算法求最短路径

  1. 初始时,S只包含起点s;U包含除s外的其他顶点,且U中顶点的距离为”起点s到该顶点的距离”[例如,U中顶点v的距离为(s,v)的长度,然后s和v不相邻,则v的距离为∞]。
  2. 从U中选出”距离最短的顶点k”,并将顶点k加入到S中;同时,从U中移除顶点k。
  3. 更新U中各个顶点到起点s的距离。之所以更新U中顶点的距离,是由于上一步中确定了k是求出最短路径的顶点,从而可以利用k来更新其它顶点的距离;例如,(s,v)的距离可能大于(s,k)+(k,v)的距离。
  4. 重复步骤(2)和(3),直到遍历完所有顶点。

以下为迪杰斯特拉算法计算最短路径的方法函数:

  Path Dijkstra()

   // 最优路径规划
    Path Dijkstra(String strStartStationName, String strEndStationName) {
        // todo: 进行一些合法性检查
        Station stationStart = mapNametoStation.get(strStartStationName);
        Station stationEnd = mapNametoStation.get(strEndStationName);
        if(stationStart==null || stationEnd==null)
        {
            System.out.println("起始站或终点输入不正确,请检查输入数据!");
            return null;
        }
        mapTransferStationNametoDistance.put(strEndStationName, nMaxDistance);
        mapTransferStationNametoDistance.put(strStartStationName, nMaxDistance);
        Path pathStart = new Path();
        pathStart.nFDistance = 0;
        pathStart.stationLastStationInPath = stationStart;
        Path Dijkstra = new Path();
        Dijkstra.nFDistance = nMaxDistance;

        Stack<Path> stackAllPaths = new Stack<>();
        stackAllPaths.push(pathStart);

        Set<String> TStationNameSet = new TreeSet<>();
        for(String strname: mapTransferStationNametoDistance.keySet()) {
              TStationNameSet.add(strname);           
                   }
        for(String strname: mapTransferStationNametoDistance.keySet()) {
              finalMap.put(strname,"null");
                   }
        while (!stackAllPaths.empty()) {
            Path pathCurrent = stackAllPaths.pop();
            if (pathCurrent.nFDistance > Dijkstra.nFDistance) {
                continue;
            }
            int nBDistance = getStationsDistance(pathCurrent.stationLastStationInPath, stationEnd);
            if (nBDistance == 0) {      // 到达终止节点
                if (pathCurrent.nFDistance < Dijkstra.nFDistance) {
                    Dijkstra = pathCurrent;
                }
                continue;
            }
            int minDistance = 1000000;
            String nextStation = null;    
            TStationNameSet.remove(pathCurrent.stationLastStationInPath.stationName);
            for (String strTStationName: mapTransferStationNametoDistance.keySet()) {
                Station stationTransfer = mapNametoStation.get(strTStationName);
                int nDistanceDelta = getStationsDistance(pathCurrent.stationLastStationInPath, stationTransfer);
                int nTStationDistance = pathCurrent.nFDistance + nDistanceDelta;
                if (nTStationDistance >= mapTransferStationNametoDistance.get(strTStationName)) {
                    continue;
                }
                finalMap.put(strTStationName,pathCurrent.stationLastStationInPath.stationName);
                mapTransferStationNametoDistance.put(strTStationName, nTStationDistance);      
            }
            for(String strTStationName: mapTransferStationNametoDistance.keySet()) {
                int Distance = mapTransferStationNametoDistance.get(strTStationName);
                if(Distance<minDistance&& TStationNameSet.contains(strTStationName)) {
                minDistance = Distance;
                nextStation = strTStationName;              
                }
            }
            Station stationTransfer = mapNametoStation.get(nextStation);
            Path pathNew = new Path();
            pathNew.nFDistance = minDistance;
            pathNew.stationLastStationInPath = stationTransfer;
            stackAllPaths.push(pathNew);
        }
        System.out.println(finalMap);
        return Dijkstra;
    }

  

打印路径 &打印指定地铁线路

stationsInLine()

Vector<String> stationsInLine(Station stationStart, Station stationEnd) {
        Vector<String> listStations = new Vector<String>();
        int nLineNumber = getLineNumber(stationStart, stationEnd);

        int nStartId = 0;
        int nEndId = 0;
        for (int nId: stationStart.setStationId) {
            if (Math.abs(nId-(nLineNumber*1000))<1000) {
                nStartId = nId;
            }
        }
        for (int nId: stationEnd.setStationId) {
            if (Math.abs(nId-(nLineNumber*1000))<1000) {
                nEndId = nId;
            }
        }
        if (nStartId == nEndId) {
            return listStations;
        }
        int nStep = 1;
        if (nEndId < nStartId) {
            nStep = -1;
        }
        int nIndexId = nStartId + nStep;
        while (nIndexId != nEndId) {
            String strSName = mapStationIdtoStation.get(nIndexId).stationName;
            listStations.addElement(strSName);
            nIndexId += nStep;
        }
        String strName = mapStationIdtoStation.get(nEndId).stationName;
        listStations.addElement(strName);
        return listStations;
    }

void printPath()

   void printPath(String start,String end, String strOutFileName) {
        String strFormatedPath = formatPath(start,end);

        toFile(strFormatedPath, strOutFileName);
    }

formatPath()

 String formatPath(String start,String end) {
        StringBuffer strRst = new StringBuffer();
        String  StartStationName=end;
        int i=1;

        int nCurrentLine = -1;

        System.out.print(finalMap);

        strRst.append(String.format("\n起始站:%s\r\n", end));
        while(end != finalMap.get(end)) {
            Station stationStart = mapNametoStation.get(end);
            Station stationEnd = mapNametoStation.get(finalMap.get(end)); 
            end = finalMap.get(end);           
            int nLineNum = Math.abs(getLineNumber(stationStart, stationEnd));           
            if (nLineNum != nCurrentLine) {
                nCurrentLine = nLineNum;
                strRst.append(String.format("%s\r\n", stationInfo.get(nLineNum)));
            }
            for (String strStationName: stationsInLine(stationStart, stationEnd)) {
                i++;
                strRst.append(String.format("%s\r\n", strStationName));
            }
            System.out.println(i);
        }
        strRst.append(String.format("\n共经过 %d 站\r\n", i));
        return strRst.toString();
    }

void toFile() 

 void toFile(String strContent, String strOutFile) {
        try {
            File file = new File(strOutFile);
            if (!file.exists()) {
                file.createNewFile();
            }
            FileWriter fileWriter = new FileWriter(file.getName(), false);

            fileWriter.write(strContent.toString());
            fileWriter.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    };

  printLineInfo()

 void printLineInfo(String LineName, String strOutFile) {
        StringBuffer strRst = new StringBuffer();
        strRst.append(String.format("地铁:%s\r\n", LineName));
        if(NtostationInfo.get(LineName)==null)
        {
            System.out.println("不存在该条地铁线路,请检查输入!\n");
            return;
        }
        int nLineNum = NtostationInfo.get(LineName);
        for (int i = 1; i < 90; i++) {
            int nStationId = nLineNum * 1000 + i;

            if (mapStationIdtoStation.containsKey(nStationId)) {
                strRst.append(mapStationIdtoStation.get(nStationId).stationName + "\r\n");
            } else {
                break;
            }
        }
        toFile(strRst.toString(), strOutFile);
    }

  

五、测试

java subway -b 洪湖里 复兴路 -map

  img

java subway -b 洪湖里 复兴路 -map subway.txt -o

    img

java subway -b 华苑  -map subway.txt -o routine

 img

java subway -a 天府广场 -map subway.txt -o station.txt

 img

java subway -b 天府广场 复兴路 -map subway.txt -o routine.txt

  img

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

 输出的station.txt文件内容:

复制代码

地铁:3号线
小淀
丰产河
华北集团
天士力
宜兴埠
张兴庄
铁东路
北站
中山路
金狮桥
天津站
津湾广场
和平路
营口道
西康路
吴家窑
天塔
周邓纪念馆
红旗南路
王顶堤
华苑
大学城
高新区
学府工业区
杨伍庄
南站

复制代码

java subway -b 刘园 西北角 -map subway.txt -o routine.txt

输出的routine.txt文件内容: 

复制代码

起始站:刘园
1号线
西横堤
果酒厂
本溪路
勤俭道
洪湖里
西站
西北角

共经过 8 站

复制代码

java subway -b 果酒厂 咸阳路 -map subway.txt -o routine.txt

输出的routine.txt文件内容: 

复制代码

起始站:果酒厂
1号线
本溪路
勤俭道
洪湖里
西站
6号线
复兴路
人民医院
长虹公园
2号线
咸阳路

共经过 9 站

复制代码

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

 img

java subway -b 天士力 土城 -map subway.txt -o routine.txt

输出的routine.txt文件内容: 

复制代码


起始站:天士力
3号线
宜兴埠
张兴庄
铁东路
北站
中山路
金狮桥
天津站
9号线
大王庄
十一经路
直沽
5号线
下瓦房
1号线
南楼
土城

共经过 14 站

复制代码

六、项目完成时间统计

PSP 2.1 Personal Software Process Stages Time
Planning 计划
· Estimate · 估计这个任务需要多少时间 3weeks
Development 开发
· Analysis · 需求分析 (包括学习新技术) 2days
· Design Spec · 生成设计文档 2days
· Design Review · 设计复审 (和同事审核设计文档) 1day
· Coding Standard · 代码规范 (为目前的开发制定合适的规范) 1day
· Design · 具体设计 2days
· Coding · 具体编码 4days
· Code Review · 代码复审 2days
· Test · 测试(自我测试,修改代码,提交修改) 2day
Reporting 报告
· Test Report · 测试报告 1day
· Size Measurement · 计算工作量 1day
· Postmortem & Process Improvement Plan · 事后总结, 并提出过程改进计划 2days
合计 20days

七.总结

  这是我第一用java编写数据结构的算法,也是我第一次用数据结构做一个有实际意义的小项目。通过本次项目,我复习回顾了java,并且对其应用有了更深的理解。同时,熟悉了idea的使用,熟悉了结对编程方式,感受到了结对编程模式的优势。

​ 在本次天津地铁路径的规划中,只将换乘站和起点终点作为需要计算的结点,从而免去了计算所有站点所带来的时间负杂度。但是,在开发过程中,也遇到了不少麻烦,比如说结对编程过程中如何高效沟通,提高我们小队的开发效率,比如在测试过程中如何保证测试用例足够全面,以确保我们的程序达到了预期需求等等。但是后来通过我们小组的不断沟通与上网查询、学习,这些问题都比较理想的解决了。

​ 总之,通过本次项目实验,让我体会到了作为一个程序员,理论和实践相结合的重要性,同时还要学会不断学习,细心观察,强化程序的健壮性和实用性。

github代码地址:https://github.com/Wanghongyu156/ck

标签:结对,String,int,汪虹余,地铁,subway,号线,txt,郑宏
来源: https://www.cnblogs.com/zhinhom/p/11814262.html