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

  還有很多東西沒優化,歡迎指出,一起學習!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM