地铁最短路径代码分析

地铁最短路径代码分析

相关链接:

https://github.com/jindsad/subwayDijkstra

实验要求说明:

根据实验要求,要实现5块部分。

1.导入txt中储存的地铁线路。

2.通过地铁线路生成地铁图,并记录每条线路的站点。

3.通过Dijkstra算法算出最短路径,储存在列表中。

4.遍历路径列表,记录线路转变,存入字符串。

5.将最短路径字符串导出txt。

模块分析:

保存站点和线路的类

站点类名Vertex包含属性有名字,相邻节点,所属线路,距离起始点最短路径,在最短路径中的上一个节点,是否已经被遍历。

public class Vertex {
    public final String name;
    public ArrayList<Vertex> neighbour=new ArrayList<Vertex>();
    public ArrayList<String> line=new ArrayList<String>();
    private int adjuDist;
    private Vertex parent;
    private boolean known=false;
}

线路类line包含线路名字,拥有的站点。

public class line {
    public final String name;
    public List<String> station;
            //=new ArrayList<String>()
    public line(String name,List<String> station){
        this.name = name;
        this.station = station;
    }
}

地铁输入txt文件格式

1号线:苹果园  ..
2号线:西直门 ..
4号线:宋河桥北 ..
5号线:宋家庄 ....

导入txt中储存的地铁线路

通过txt路径将地铁按行保存在List列表中,一行为一条线路。

方法名inputmapname

    public List<String>  inputmapname(String mapname){
          List<String> list = new ArrayList<String>();
          String line =new String();
        try (FileReader reader = new FileReader(mapname);
                BufferedReader br = new BufferedReader(reader);
           ) {
            while ((line = br.readLine()) != null) {
              if (line.lastIndexOf("---") < 0) {
                  list.add(line);
              }
          }
          return list;
           } catch (IOException e) {
               e.printStackTrace();
           }
        return null;

    }

通过地铁线路生成地铁图,并记录每条线路的站点

向线路添加站点

通过inputmapname方法将线路字符串存在list中,先用split将字符串按:分割,str[0]为名称,str[1]为站点。再将str[1]按“ ”分割得出每个站点名,将站点名保存在line类中,并用一个List station记录所有站点。station中的所有Vertex先不记录线路信息和相邻节点信息。

List<String> map=a.inputmapname(inputname);

for(int b=0;b<map.size();b++) {

//向线路加入站点
            List<String> s=new ArrayList<String>();
                String[] str;
                str = map.get(b).split(":");
                String[] sta;
                sta = str[1].split(" ");
                for(int st=0;st<sta.length;st++) {
                    s.add(sta[st]);
                }
                line li=new line(str[0],s);
                line.add(li);
                for(int st=0;st<sta.length;st++) {
                Vertex ve=new Vertex(sta[st]);
                int t=0;
                for(int op=0;op<station.size();op++) {
                    if(station.get(op).name.equals(sta[st])) {
                        t=1;
                        break;
                    }
                }
                if(t==0)station.add(ve);
            }

        }

向站点传入相邻节点信息和所属站点

在传入线路时,已经将站点名存入station中,需要向站点添加相邻站点和线路,将txt文件重新导入,重新得到各线路站点,

将得到的站点遍历和station中进行比较,寻找出名字为sta[st+1]的站点和sta[st-1]的站点。并将寻找出String[st]对应的站点,将String[st+1]和String[st-1]对应的站点加入相邻站点中,并将站点对应的线路存入站点中

List<String> map=a.inputmapname(inputname);
for(int b=0;b<map.size();b++) {
//向线路加入站点
List<String> s=new ArrayList<String>();
String[] str;
str = map.get(b).split(":");
String[] sta;
sta = str[1].split(" ");
for(int st=0;st<sta.length;st++) {
int nu1=-1;
int nu2=-1;
for(int st1=0;st1<station.size();st1++) {
if(st>0&&station.get(st1).toName().equals(sta[st-1])) {
nu1=st1;
}
if(st<sta.length-1&&station.get(st1).toName().equals(sta[st+1])) {
nu2=st1;
}
if(nu2!=-1&&nu1!=-1)break;
}
for(int st1=0;st1<station.size();st1++) {
if(station.get(st1).toName().equals(sta[st])) {
if(nu1!=-1)station.get(st1).neighbour.add(station.get(nu1));
if(nu2!=-1)station.get(st1).neighbour.add(station.get(nu2));
station.get(st1).line.add(str[0]);
break;
}}}}

去除一个节点的重复线路

北京线路中会存在环形线路,我将这样的线路头尾用一个站点保存,使其构成环路,所以对站点添加线路名字时,会出现同一站点线路重复,所以需要去重,使用方法trimList去除相同元素。

    private static ArrayList trimList(ArrayList list) {
        ArrayList list2 = new ArrayList();
        for (int i = list.size() - 1; i >= 0; i--) {
        Object o = list.get(i);
        if (list2.indexOf(o) == -1) {
        list2.add(0, o);
        }
        }
        return list2;
        }

通过Dijkstra算法算出最短路径,储存在列表中

用递归,当站点为空返回空,对站点v的相邻站点进行遍历,如果相邻点没有被访问过,就将其路径更改为v.getAdjuDist()+1 ,其父节点为v,如果相邻点的最短路径比v.getAdjuDist()+1 小这不做更改,如果相邻节点的最短路径比v.getAdjuDist()+1 ,更新最短路径为v.getAdjuDist()+1 。把所有相邻节点递归,直到所有节点遍历完成。

 private void updateChildren(Vertex v)
        {
         if (v==null) {
                return;
            }
         if(v.neighbour==null||v.neighbour.size()==0) {
             return;
         }
         List<Vertex> childrenList = new LinkedList<Vertex>();
         for(int a=0;a<v.neighbour.size();a++){
            if(v.getParent()==null||!v.getParent().equals(v.neighbour.get(a))) {
             Vertex childVertex=v.neighbour.get(a);
             if(!childVertex.isKnown())
                {
                    childVertex.setKnown(true);
                    childVertex.setAdjuDist(v.getAdjuDist()+1);
                    childVertex.setParent(v);
                    childrenList.add(childVertex);
                }
             int nowDist = v.getAdjuDist()+1;
             if(nowDist>=childVertex.getAdjuDist())
                {
                    continue;
                }
             else {
                    childVertex.setAdjuDist(nowDist);
                    childVertex.setParent(v);
                    childrenList.add(childVertex);
             }
             }

         }
         for(Vertex vc:childrenList)
            {
                updateChildren(vc);
            }
        }

遍历路径列表,记录线路转变,存入字符串。

通过dijkstraTravasal输出最短路径站点,需要判断转站点。遍历每个ar的站点,用xian储存现在站点的线路,判断每个站点的前一个节点和后一个节点,如果站点改变则转成下一站点的线路,如果现有线路的xian改变,则也进行转站。将站点和转站线路保存在pa中用outputmap返回。

ar=dik.dijkstraTravasal(station, place1, place2);
String pa=String.valueOf(ar.size())+"\r\n";

String xian="";

for(int num=0;num<ar.get(ar.size()-1).line.size();num++) {
                     for(int num1=0;num1<ar.get(ar.size()-2).line.size();num1++) {
                         if(ar.get(ar.size()-1).line.get(num).equals(ar.get(ar.size()-2).line.get(num1))) {
                             xian=ar.get(ar.size()-1).line.get(num);
                             break;
                         }
                         if(!xian.equals(""))break;
                     }
                }
                for(int num=ar.size()-1;num>=0;num--) {
                    int y=0;
                    pa=pa+ar.get(num).toName()+"\r\n";
                    if(ar.get(num).line.size()>1&&num!=0&&num!=ar.size()-1){
                        for(int num1=0;num1<ar.get(num-1).line.size();num1++) {
                            for(int num2=0;num2<ar.get(num+1).line.size();num2++) {
                                if(ar.get(num-1).line.get(num1).equals(ar.get(num+1).line.get(num2))) {
                                    y=1;
                                    break;
                                }
                                if(y==1)break;
                            }
                        }
                        for(int num2=0;num2<ar.get(num-1).line.size();num2++) {
                        if(ar.get(num-1).line.get(num2).equals(xian)) {
                            break;
                        }
                        if(num2==ar.get(num-1).line.size()-1)y=0;
                        }
                        if(y==0) {
                            String hua="";
                            for(int num1=0;num1<ar.get(num).line.size();num1++) {
                                for(int num2=0;num2<ar.get(num-1).line.size();num2++) {
                                    if(ar.get(num).line.get(num1).equals(ar.get(num-1).line.get(num2))) {
                                        hua=ar.get(num-1).line.get(num2);
                                        xian=hua;
                                        break;
                                    }
                                    if(y==1)break;
                                }
                            }
                        pa=pa+hua+"\r\n";
                        }
                    }
                }

-a输出line线路

        for(int b=0;b<line.size();b++) {
            if(line1.equals(line.get(b).name)) {
                for(int b1=0;b1<line.get(b).station.size();b1++) {
                    line2=line2+" "+line.get(b).station.get(b1);
                }
                break;
            }
        }

程序结果展示

输入:

-b 良乡大学城 双桥 -map C:\Users\Shinelon\eclipse-workspace\软件工程个人作业\src\软件工程个人作业\北京地铁图1.txt  -o C:\Users\Shinelon\eclipse-workspace\软件工程个人作业\src\软件工程个人作业\station.txt

输出:

原文地址:https://www.cnblogs.com/jgxjav/p/11654096.html

时间: 2024-08-02 14:02:47

地铁最短路径代码分析的相关文章

个人项目——地铁最短路径简要分析

github 个人博客 一.项目计划: 实现一个帮助进行地铁出行路线规划的命令行程序. 二.项目需求: 1.该程序能够准确地读出.txt文件中的数据,文件格式简洁易懂.可灵活扩展 2.在某号线路上,能够查询各个站点的信息,输出该号线路上所有站点信息 3.在出发站与目的站之间输出一个最短路径 4.用PSP记录在程序的各个模块上实际花费的时间. PSP表如下: PSP 2.1 Personal Software Process Stages Time Planning 计划 1d   · Estim

北京地铁最短路径实现

北京地铁最短路径规划 github地址 github 需求理解 将地铁线路保存成一个可读入,简洁明了的文本 程序能正确读入这个文件,并获取地铁线路信息 程序能正确处理输入的命令行 地铁能正确输出指定地铁线经过的站点 程序能正确输出两个站点间的最短路径 程序要有健壮性,能通过各类性能测试 按要求编写博客,详细说明花费时间,代码,各个模块和测试用例 文本存储方式 该文本直接保存进了各条线路的各个站点,没有在文本中考虑换乘点.当读入"一号线"等文字时,将它转换为线路的id号,然后在way数组

结队编程,地铁最短路径,张波-朱新远

结对编程 地铁最短路径 一.任务: 实现一个帮助进行地铁出行路线规划的命令行程序. PSP 2.1 Personal Software Process Stages Time Planning 计划     · Estimate   · 估计这个任务需要多少时间  7d Development 开发     · Analysis   · 需求分析 (包括学习新技术)  2d   · Design Spec   · 生成设计文档 1d    · Design Review   · 设计复审 (和同

结对编程 地铁最短路径 张波-朱新远

结对编程 地铁最短路径 一.任务: 实现一个帮助进行地铁出行路线规划的命令行程序. PSP 2.1 Personal Software Process Stages Time Planning 计划     · Estimate   · 估计这个任务需要多少时间  7d Development 开发     · Analysis   · 需求分析 (包括学习新技术)  2d   · Design Spec   · 生成设计文档 1d    · Design Review   · 设计复审 (和同

java代码分析及分析工具

java代码分析及分析工具 一个项目从搭建开始,开发的初期往往思路比较清晰,代码也比较清晰.随着时间的推移,业务越来越复杂.代码也就面临着耦合,冗余,甚至杂乱,到最后谁都不敢碰. 作为一个互联网电子商务网站的业务支撑系统,业务复杂不言而喻.从09年开始一直沿用到现在,中间代码经过了多少人的手,留下了多少的坑,已经记不清楚了,谁也说不清了. 代码的维护成本越来越高.代码已经急需做调整和改善.最近项目组专门设立了一个小组,利用业余时间做代码分析的工作,目标对核心代码进行分析并进行设计重构. 代码分析

Java静态代码分析工具Infer

Java静态代码分析工具Infer 作者:chszs,转载需注明.博客主页:http://blog.csdn.net/chszs 一.Infer介绍 Infer是Facebook最新开源的静态程序分析工具,用于在发布移动应用之前对代码进行分析,找出潜在的问题.目前Facebook使用此工具分析Facebook的App,包括Android.iOS.Facebook Messenger和Instagram等. Facebook称该工具帮助其每个月检查出应用潜在的数百个Bug,例如一些空指针访问.资源

$*和[email&#160;protected]之间区别代码分析

#!/bin/bash set 'apple pie' pears peaches for i in $*           /*单引号被去掉,循环单个字符输出*/ do echo $i done [[email protected] Ex_14.02-14.31]# sh 14-14-1 apple pie pears peaches -------------------------------------------------------------- #!/bin/bash set

《linux 内核完全剖析》 keyboard.S 部分代码分析(key_map)

keyboard.S 部分代码分析(key_map) keyboard中间有这么一段,我一开始没看明白,究竟啥意思 key_map: .byte 0,27 .ascii "1234567890-=" .byte 127,9 .ascii "qwertyuiop[]" .byte 13,0 .ascii "asdfghjkl;'" .byte '`,0 .ascii "\\zxcvbnm,./" .byte 0,'*,0,32

20145234黄斐《网络对抗技术》实验四,恶意代码分析

恶意代码 概述 恶意代码是指故意编制或设置的.对网络或系统会产生威胁或潜在威胁的计算机代码.最常见的恶意代码有计算机病毒(简称病毒).特洛伊木马(简称木马).计算机蠕虫(简称蠕虫).后门.逻辑炸弹等. 特征: 恶意的目的,获取靶机权限.用户隐私等 本身是计算机程序,可以执行,并作用于靶机 通过执行发生作用,一般来说不运行是没问题的 恶意代码分析 在大多数情况下,进行恶意代码分析时,我们将只有恶意代码的可执行文件本身,而这些文件并不是我们人类可读的.为了了解这些文件的意义,你需要使用各种工具和技巧