1. 程式人生 > >Dijkstra演算法(matlab)

Dijkstra演算法(matlab)

Dijkstra演算法是尋找最短路徑的一種搜尋演算法,由荷蘭科學家提出。

演算法描述:通過為每個節點保留目前為止所找到的從s到e的最短路徑。為了記錄最佳路徑軌跡,記錄路徑上每個節點的前趨,通過回溯法找出最短路徑軌跡。


在網上搜索一些版本的Matlab實現方法,感覺都有些毛病。經過修改,得到比較好的效果。

function [ distance path] = Dijk( W,st,e )
%DIJK Summary of this function goes here
%   W  權值矩陣   st 搜尋的起點   e 搜尋的終點
n=length(W);%節點數
D = W(st,:);
visit= ones(1:n); visit(st)=0;
parent = zeros(1,n);%記錄每個節點的上一個節點

path =[];

for i=1:n-1
    temp = [];
    %從起點出發,找最短距離的下一個點,每次不會重複原來的軌跡,設定visit判斷節點是否訪問
    for j=1:n
       if visit(j)
           temp =[temp D(j)];
       else
           temp =[temp inf];
       end
       
    end
    
    [value,index] = min(temp);
   
    visit(index) = 0;
    
    %更新 如果經過index節點,從起點到每個節點的路徑長度更小,則更新,記錄前趨節點,方便後面回溯循跡
    for k=1:n
        if D(k)>D(index)+W(index,k)
           D(k) = D(index)+W(index,k);
           parent(k) = index;
        end
    end
    
   
end

distance = D(e);%最短距離
%回溯法  從尾部往前尋找搜尋路徑
t = e;
while t~=st && t>0
 path =[t,path];
  p=parent(t);t=p;
end
path =[st,path];%最短路徑


end

測試:

測試用例1

W=[0 50 inf 40 25 10
    50 0 15 20 inf 25
    inf 15 0 10 20 inf 
    40 20 10 0 10 25
    25 inf 20 10 0 55
    10 25 inf 25 55 0];
[distance,path]=Dijk(W,1,4);
>> distance


distance =


    35


>> path


path =


     1     6     4


從節點1到節點4最短距離路徑為1-->6-->4, 最短距離為35

測試用例2

W=[0 1 3 4
    1 0 2 inf
    3 2 0 5
    4 inf 5 0];
[distance,path]=Dijk(W,2,4);
>> distance


distance =


     5


>> path


path =


     2     1     4
從節點2到節點4最短距離路徑為2-->1-->4, 最短距離為5

java版dijkstra

import java.util.HashMap;
import java.util.Map;

/**
 * Created by zhangjackie on 18/5/2.
 */
public class DijkstraShortPath {
    private static final int N = 1000;
    private static int[][] graph = {
            {0, 7, 9, N, N, 14},
            {7, 0, 10, 15, N, N},
            {9, 10, 0, 11, N, 2},
            {N, 15, 11, 0, 6, N},
            {N, N, N, 6, 0, 9},
            {14, N, 2, N, 9, 0}
    };

    private static void dijkstra(int vstart, int[][] graph) {
        int n = graph.length;
        int[] dist = new int[n];
        boolean[] visit = new boolean[n];
        int[] prev = new int[n];
        Map<Integer, String> path = new HashMap<Integer, String>();
        int vnear = vstart;

        //初始化
        for (int i = 0; i < n; i++) {
            dist[i] = graph[vstart][i];
            visit[i] = false;
            prev[i] = vstart;
        }

        visit[vstart] = true;


        for (int i = 1; i < n; i++) {
            int min = N;
            //尋找最近的節點
            for (int j = 0; j < n; j++) {
                if (!visit[j] && dist[j] < min) {
                    min = dist[j];
                    vnear = j;
                }
            }

            visit[vnear] = true;

            //更新dist,記錄前一執行節點
            for (int k = 0; k < n; k++) {
                int minDist = min + graph[vnear][k];
                if (!visit[k] && minDist < dist[k]) {
                    dist[k] = minDist;
                    prev[k] = vnear;
                }
            }
        }

        //列印最短路徑
        for (int i = 0; i < n; i++) {
            int preprev = prev[i];
            path.put(i,Integer.toString(i));
            while (preprev != vstart) {
                String oldpath = path.get(i);
                path.put(i, preprev + "->" + oldpath);
                preprev = prev[preprev];
            }

            String oldpath = path.get(i);
            path.put(i,  vstart +"->" + oldpath);
        }

//        System.out.println(Arrays.toString(dist));
        for (int i = 0; i < n; i++) {
//            System.out.println("v" + vstart + "...v" + prev[i] + "->v" + i + ", s=" + dist[i]);
            System.out.println(path.get(i)  + ", s=" + dist[i]);
        }

    }


    public static void main(String[] args) {
        dijkstra(3, graph);
    }

}