基於Dijkstra算法,實現求城市之間最短距離

源代碼存放在git,其中還有其他算法實現:https://github.com/zhangpei

git地址bisha/dataStructure.git

https://github.com/zhangpeibisha/dataStructure.git
https://github.com/zhangpeibisha/dataStructure.git
https://github.com/zhangpeibisha/dataStructure.git
https://github.com/zhangpeibisha/dataStructure.git

dijkstra算法簡單思想:

1.使用兩個集合,一個存已經遍歷了的節點,一個存還未遍歷的節點。集合格式{U(10)}代表起點到U節點距離爲10

2.基於廣度遍歷

3.求解兩步走:

第一步,找到還未訪問節點,且其中最短路徑的節點,並將這個最短路徑存入已經遍歷的節點。

第二部,通過找到的最短路徑節點,去修正其他爲訪問節點到起點的最短路徑。

上代碼:

city類:

import java.util.ArrayList;
import java.util.List;

/**
 * Create by [email protected] on 2018/4/22.
 */
public class City {

    // 城市名字
    private String cityName;

    // 與該城市鄰接的城市
    private List<Distance> distance;

    public City() {
        init();
    }

    /**
     * 初始化這個對象,因爲當前城市到當前城市的距離默認爲0
     */
    public void init() {
        distance = new ArrayList<>();
        distance.add(new Distance(this, this, 0.0));
    }

    public String getCityName() {
        return cityName;
    }

    public void setCityName(String cityName) {
        this.cityName = cityName;
    }

    public List<Distance> getDistance() {
        return distance;
    }

    public void setDistance(List<Distance> distance) {
        this.distance = distance;
    }

    public City addDistance(City toCity) {
        this.distance.add(new Distance(this, toCity));
        return this;
    }

    public City addDistance(City toCity, double distance) {
        this.distance.add(new Distance(this, toCity, distance));
        return this;
    }


}

Distance類:

/**
 * Create by [email protected] on 2018/4/22.
 *
 * 此爲原始路徑距離
 */
public class Distance {

    // 起點城市
    private City fromCity;

    // 目的城市
    private City toCity;

    // 兩個城市之間的距離  爲空則爲無窮大
    private double distance = Integer.MAX_VALUE-1;

    public Distance(City fromCity, City toCity) {
        this.fromCity = fromCity;
        this.toCity = toCity;
    }

    public Distance(City fromCity, City toCity, double distance) {
        this.fromCity = fromCity;
        this.toCity = toCity;
        this.distance = distance;
    }

    public City getFromCity() {
        return fromCity;
    }

    public void setFromCity(City fromCity) {
        this.fromCity = fromCity;
    }

    public City getToCity() {
        return toCity;
    }

    public void setToCity(City toCity) {
        this.toCity = toCity;
    }

    public Double getDistance() {
        return distance;
    }

    public void setDistance(Double distance) {
        this.distance = distance;
    }
}

ShortPath類:

/**
 * Create by [email protected] on 2018/4/22.
 *
 * 城市與城市之間的最短路徑
 */
public class ShortPath {

    // 出發城市
    private City fromCity;

    // 目的城市
    private City toCity;

    // 途徑地
    private Queue<City> ways;

    // 兩個城市之間的需要走的距離
    private Double distance;

    public ShortPath(City fromCity, City toCity) {
        this.fromCity = fromCity;
        this.toCity = toCity;
    }

    public City getFromCity() {
        return fromCity;
    }

    public void setFromCity(City fromCity) {
        this.fromCity = fromCity;
    }

    public City getToCity() {
        return toCity;
    }

    public void setToCity(City toCity) {
        this.toCity = toCity;
    }

    public Queue<City> getWays() {
        return ways;
    }

    public void setWays(Queue<City> ways) {
        this.ways = ways;
    }

    public Double getDistance() {
        return distance;
    }

    public void setDistance(Double distance) {
        this.distance = distance;
    }
}

Dijkstra類:

import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

/**
 * Create by [email protected] on 2018/4/22.
 * <p>
 * 具體算法
 */
public class CityDijKstra {

    // 起點城市
    private final City startCity;

    private final City endCity;

    // 使用鄰接矩陣表示地圖
    private List<City> map;

    // 求出來的最短路徑結果保存,若爲空則沒有路徑可達
    private ShortPath shortPath;

    public CityDijKstra(City startCity, City endCity, List<City> map) {
        this.startCity = startCity;
        this.endCity = endCity;
        this.map = map;
        init();
    }

    private void dijkstra(int citySize, int startIndex, int endIndex) {

        // 保存起點城市到其他城市的最短長度
        double[] shortPath = new double[citySize];
        // 標記城市是否被求的最短路徑
        boolean[] marked = new boolean[citySize];
        // 保存最短路徑訪問
        Queue<City>[] paths = new LinkedList[citySize];
        // 起點和其他點的距離
        List<Distance> startDistance = map.get(startIndex).getDistance();

        //初始化paths
        for (int i = 0; i < citySize; i++) {
            Queue<City> queue = new LinkedList<>();
            queue.offer(startCity);
            queue.offer(map.get(i));
            paths[i] = queue;
        }

        // 自己訪問自己距離爲0 且不必在求最短路徑,因此標記爲true
        shortPath[startIndex] = 0;
        marked[startIndex] = true;

        for (int i = 1; i < citySize; i++) {

            /**
             * 此部分計算起點到其他爲標記點中最短路徑的那個點
             */
            // 記錄頂點能到達點的最短距離的下標
            int k = -1;
            // 距離爲Integer.MAX_VALUE表示不可達
            double mind = Integer.MAX_VALUE;

            for (int j = 0; j < citySize; j++) {

                double dis = startDistance.get(j).getDistance();

                if (!marked[j] && dis < mind) {
                    mind = dis;
                    k = j;
                }
            }

            shortPath[k] = mind;
            marked[k] = true;

            /**
             * 此部分根據k點修正起點到其他所有節點的前驅節點及距離
             */

            for (int j = 0; j < citySize; j++) {

                //起點到k點的最短距離 + k點到j點的最短距離
                double dis = startDistance.get(k).getDistance() +
                        map.get(k).getDistance().get(j).getDistance();

                // 判斷j點是否被標記,若沒有被標記,且dis小於直達距離,則修正最短距離
                if (!marked[j] && dis < startDistance.get(j).getDistance()) {

                    map.get(startIndex)
                            .getDistance()
                            .get(j).setDistance(dis);

                    Queue<City> queue = new LinkedList<>();
                    for (City city : paths[k]) {
                        queue.offer(city);
                    }
                    queue.offer(map.get(j));
                    paths[j] = queue;
                }
            }
        }
        display(shortPath, paths);
        this.shortPath.setDistance(shortPath[endIndex]);
        this.shortPath.setWays(paths[endIndex]);
    }


    private void init() {
        // 初始化最短路徑結果中的起始城市和目的城市
        shortPath = new ShortPath(startCity, endCity);
        int citySize = map.size();
        int startIndex = map.indexOf(startCity);
        int endIndex = map.indexOf(endCity);
        dijkstra(citySize, startIndex, endIndex);
        display(map);
    }

    private void display(double[] dis, Queue<City>[] paths) {

        for (int i = 0; i < dis.length; i++) {
            System.out.print(startCity.getCityName() + "到" + map.get(i).getCityName());
            System.out.print("的距離爲:" + dis[i]);
            System.out.println();
            System.out.print(startCity.getCityName() + "到" + map.get(i).getCityName());
            System.out.print("的路徑爲:");
            for (City city : paths[i]) {
                System.out.print(city.getCityName() + " ");
            }
            System.out.println();
        }
    }

    private void display(List<City> cities){
        System.out.println("==========================");
        for (City city : cities) {
            for (int i = 0; i <city.getDistance().size() ; i++) {
                System.out.print(city.getCityName() + "到");
                if (city.getDistance().get(i).getDistance() < Integer.MAX_VALUE/2)
                System.out.print(city.getDistance().get(i).getToCity().getCityName() +
                        "距離爲" +
                        city.getDistance().get(i).getDistance());
                else
                    System.out.print(city.getDistance().get(i).getToCity().getCityName() +
                            "距離爲不可達");
                System.out.println();
            }

        }
    }
}

測試類:ShortPahtTest:

import java.util.ArrayList;
import java.util.List;

/**
 * Create by [email protected] on 2018/4/22.
 * <p>
 * 最短路徑算法測試
 */
public class ShortPathTest {

    public static void main(String[] args) {

        double MAX = Integer.MAX_VALUE;

        City chongqing = new City();
        chongqing.setCityName("重慶0");

        City guangzhou = new City();
        guangzhou.setCityName("廣州1");

        City shenzheng = new City();
        shenzheng.setCityName("深圳2");

        City huizhou = new City();
        huizhou.setCityName("惠州3");

        City shanghai = new City();
        shanghai.setCityName("上海4");


        chongqing.addDistance(guangzhou,10.0)
                .addDistance(shenzheng)
                .addDistance(huizhou,30.0)
                .addDistance(shanghai,100.0);

        guangzhou.addDistance(chongqing)
                .addDistance(shenzheng,50.0)
                .addDistance(huizhou)
                .addDistance(shanghai);

        shenzheng.addDistance(guangzhou)
                .addDistance(chongqing)
                .addDistance(huizhou)
                .addDistance(shanghai,10.0);

        huizhou.addDistance(guangzhou)
                .addDistance(shenzheng,20.0)
                .addDistance(chongqing)
                .addDistance(shanghai,60.0);

        shanghai.addDistance(guangzhou)
                .addDistance(shenzheng)
                .addDistance(huizhou)
                .addDistance(chongqing);

        List<City> cities = new ArrayList<City>();
        cities.add(chongqing);
        cities.add(guangzhou);
        cities.add(shenzheng);
        cities.add(huizhou);
        cities.add(shanghai);

        CityDijKstra cityDijKstra = new CityDijKstra(chongqing,shenzheng,cities);
    }

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章