个人项目——北京地铁线路规划

Posted 31701424_王志伟

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了个人项目——北京地铁线路规划相关的知识,希望对你有一定的参考价值。

一、前言

现实和理想的差距总是那么大,在过程中碰到的坑比预期的还多(说那么多,其实就是自己菜),过程中复习了淡忘已久的许多算法和数据结构,一边深刻的体会着自己是多菜,一边也体会到了自身一点点微小的进步,大概。

 

二、项目简介

实现北京地铁查询功能

附上一张北京地铁的图:

  

三、项目地址

https://github.com/fireworks-EX/MetroLinePlanning

四、需求分析

1、确定储存及读取地铁线路数据文件的格式

2、支持用户输入的地铁线路的查询

3、提供用户指定两站点间的最短乘车路径的方案(可换乘)

五、数据存储格式

1、subway.txt存储的地图数据文本,使用json格式:

[
    {
        \'Line\' : \'S1线\',
        \'Station\' : [\'金安桥\', \'四道桥\', \'桥户营\', \'上岸\', \'栗园庄\', \'小园\', \'石厂\']
    },
        ………………
        ………………
        ………………
]

\'Line\'为线路名称,\'Station\' 为站名。

2、数据的读取和保存

    public static String readJsonData(String pactFile){    //读入json格式的地铁路线信息
        StringBuffer strbuffer = new StringBuffer();
        File myFile = new File(pactFile);
        if (!myFile.exists()) {
            System.err.println("没有找到文件: " + pactFile);
        }
        try {
            FileInputStream fis = new FileInputStream(pactFile);
            InputStreamReader inputStreamReader = new InputStreamReader(fis, "GBK");
            BufferedReader in  = new BufferedReader(inputStreamReader);            
            String str;
            while ((str = in.readLine()) != null) {
                strbuffer.append(str);
            }
            in.close();
        } catch (IOException e) {
            e.getStackTrace();
        }
        return strbuffer.toString();
    }
    
    public static String getPath(String fileName) {        //获取文件路径
        String path = Subway.class.getResource("").toString() + fileName;
        path = path.replace("file:/", "");
        path = path.replace("/", "//");
        return path;
    }
    
    public static boolean save(String path, String sets) throws IOException {    //保存文件
        FileWriter fw;
        File f=new File(path);
        if (!f.exists()) {
            f.createNewFile();
        }
        FileOutputStream fos1=new FileOutputStream(f);
        OutputStreamWriter dos1=new OutputStreamWriter(fos1);
        dos1.write(sets);
        dos1.write("\\n");
        dos1.close();

        return true;
    }

运行截图:

主界面:

 

读取成功提示:

读取成功后显示地铁线路所有信息:

 

 

 

 UI自己写的,太丑勿喷

六、具体功能实现

因为地铁线是无向图,若用邻接矩阵存会是稀疏矩阵对空间浪费较大,故采用邻接表。

1、邻接表定义:

    public class ENode {//定义边节点
        int ivex;       // 该边所指向的顶点的位置
        ENode nextEdge; // 指向下一条弧的指针
    }

    public class VNode {    //定义顶点节点
        final static int inf = Integer.MAX_VALUE; //代表距离无限大
        String data;        // 顶点信息(站点名字)
        ENode firstEdge;    // 指向该顶点所连接的边
        int dist;            // 距离
        boolean flag;        // 标记(是否被访问过,dijkstra算法中用到)
        VNode parent;        // 父节点(即前一站)
        
        public VNode() {        //无参构造器
            this.dist = inf;    //初始化距离为无限大
            this.flag = false;    //初始化节点未访问
            this.parent=null;    //初始化父结点为空
        }
    }
   
    private static VNode[] mVexs;      // 顶点数组(构造邻接表)

这里其实写麻烦了,跟当初写C语言一样自己定义,弄得后面功能实现麻烦了很多,如果用map之类的写会简单很多。

2、bfs计算最短路径:

    private static void bfs(VNode v1, String s){  //更新路径信息
        List<VNode> queue = new LinkedList<VNode>();
        queue.add(v1);
        while(true) {
            int count=queue.size();
            for(int i=0;i<count;i++) {
                VNode v = queue.get(0);
                if(v != null) {
                    ENode node = v.firstEdge;
                    while (node != null) {
                        VNode childVNode = mVexs[node.ivex];
                        if(childVNode.flag==false)
                        {
                            childVNode.flag=true;        //将标志置为true,表示该节点已被访问
                            childVNode.dist=v.dist+1;    //距离+1
                            childVNode.parent=v;        //将该节点设为父结点(为了便于回溯)
                            if(childVNode.data.equals(s)) return;
                            queue.add(childVNode);
                        }
                        node = node.nextEdge;
                    }
                }
                queue.remove(0);
            }
        }

    }

按自己的理解写的,没参考网上代码,可能比较垃圾,不要见怪

就本题而言,bfs实现简单,而且当我们找到终点时可以直接终止循环。

 

3、………………

其他代码太长就不贴了,具体可去我的GitHub上看,链接已在文章开头给出

顺便附上部分运行截图:

查看某指定路线:

 查询两站点间最短路径:

 

 该最短路径可以保存到本地txt文件:

 因为获取了开始读取的subway.txt中的线路站点信息,并用下拉框的形式进行选择,确保了不会有非法输入,省去了异常判断的处理。

 

附录:

GitHub下载请自行把bin和src目录下的代码丢进相应文件夹下,如果报红,原因是json的jar包还没有导入:

     

 

发现我的数据文件忘记上传了,尴尬,请把subway.txt放在bin目录下。

现已重新上传subway.txt至bin目录下,直接运行就好。

以上是关于个人项目——北京地铁线路规划的主要内容,如果未能解决你的问题,请参考以下文章

北京地铁线路规划

个人项目——地铁线路规划

北京地铁最短线路规划

北京地铁线路规划系统

北京地铁线路规划

北京地铁线路规划