zoukankan      html  css  js  c++  java
  • Java用Dijkstra算法实现地图两点的最短路径查询(Android版)

      地图上实现最短路径的查询,据我了解的,一般用Dijkstra算法和A*算法来实现。由于这是一个课程项目,时间比较急,而且自己不熟悉A*算法,所以参考网上的Dijkstra算法(http://blog.csdn.net/javaman_chen/article/details/8254309)的代码来实现了地图上任意两点的最短路径的查询。但该demo存在一个很严重的错误,缺了两行非常关键的代码……

      首先,来了解下Dijkstra算法:无向图的最短路径求解算法之——Dijkstra算法 http://sbp810050504.blog.51cto.com/2799422/690803 。由此可以看出,Dijkstra算法的效率是很低的,它遍历的点很多,要以起始点为中心向外层层扩展,直到扩展到终点为止,所以数据量很少时不适合Dijkstra算法。处理该算法时,要特别注意在由一个点找到相邻该点最近点的时候,记得要将相邻的点的距离更新。

      Dijkstra一般的表述通常有两种方式,一种用永久和临时标号方式,一种是用OPEN, CLOSE表的方式,这里是采用第二种方式,也就是采用的贪心法的算法策略,大概过程如下:
      1.定义两个集合:open和close,open用于存储未遍历的节点,close用来存储已遍历的节点;
      2.初始阶段,将初始节点放入close,其他所有节点放入open;
      3.以初始节点为中心向外一层层遍历,获取离指定节点最近的子节点放入close并重新更新相邻点的距离,直至close包含所有子节点;

      此方法由一个点遍历了其他所有点,所以可以知道该点到其他所有点的距离,时间复杂度很高。那个demo是一个一个数据初始化的,我将它改为用数组存储,然后用for循环来初始化,也就是将它封装成我需要的数据接口,并没有很大的优化。

      算法核心只有两个函数:

    /**
         * 获取与node最近的子节点
         */
        private Node getShortestPath(Node node) {
            Node res = null;
            int minDis = Integer.MAX_VALUE;
            Map<Node, Integer> childs = node.getChild();
    
            // 循环比较,找出离node最近的子节点
            for (Node child : childs.keySet()) {
                if (open.contains(child)) {
                    int distance = childs.get(child);
                    if (distance < minDis) {
                        minDis = distance;
                        res = child;
                    }
                }
            }
            return res;
        }
    View Code
    public void computePath(Node start) {
            Node nearest = getShortestPath(start);// 取距离start节点最近的子节点,放入close
            if (nearest == null) {
                return;
            }
            close.add(nearest);
            open.remove(nearest);
            Map<Node, Integer> childs = nearest.getChild();
            for (Node child : childs.keySet()) {
                if (open.contains(child)) {// 如果子节点在open中
                    Integer newCompute = path.get(nearest.getName()) + childs.get(child);
                    if (path.get(child.getName()) > newCompute) {// 之前设置的距离大于新计算出来的距离
                        path.put(child.getName(), newCompute);
                        
                        start.getChild().put(child, newCompute);
                        close.add(start);
                        
                        pathInfo.put(child.getName(), pathInfo.get(nearest.getName()) + "-" + child.getName());
                    }
                }
            }
            computePath(start);// 重复执行自己,确保所有子节点被遍历
            computePath(nearest);// 向外一层层递归,直至所有顶点被遍历
        }
    View Code

      那个demo漏了两行代码,就是找到最近的路径后,没有更新相邻点的距离

      start.getChild().put(child, newCompute);
      close.add(start);

      这是一个Android平板的应用,代码在:http://pan.baidu.com/share/link?shareid=3275093017&uk=3726801344

      还有很多东西没优化,欢迎指出,一起学习!

  • 相关阅读:
    java基础3 循环语句:While 循环语句、do while 循环语句、 for 循环语句 和 break、continue关键字
    java基础2 判断语句:if ... else 语句和 switch 语句
    IT行业经典面试技巧及方法思路。
    Java基础1,入门基础知识
    SVN的使用、分支合并及解决冲突详解
    VC工程产生文件后缀名解释
    ireport报表,打印时,报表加载失败的解决方法
    MySQL 事务、视图、索引
    MySQL高级查询
    MySQL中的主键约束和外键约束
  • 原文地址:https://www.cnblogs.com/navyifanr/p/3332203.html
Copyright © 2011-2022 走看看