매일 알고리즘 : 다 익스트라 알고리즘

소개

Dijistra최단 경로 알고리즘의 알고리즘은도 다른 노드들에 하나 개의 노드에서의 최단 거리를 계산하기 위해 사용될 수있다.
당신이 중간 점을 찾을 때까지 주로 발견 층의 아이디어를 통해 중앙 노드에서 바깥쪽으로 확장합니다.
방향성 그래프와 유향 그래프에 적합합니다.

알고리즘

  1. 우리는 노드를 계산한다고 가정 A다른 노드 최단 거리를
  2. 두 세트 (도입 S, U) 세트는, 상기 S최단 경로를 나타내는 컬렉션은 결정된 포인트 (최단 거리)이었다 U결정되지 않은 최단 경로의 시점을 나타낸다. 요소의 세트와 유사한 A(0)상기 표현 A대상 점은 A, (0)최단 경로를 나타냄이 알려져있다 0(비와 직접 통신로 표시).
  3. 우선, S그것은 단지 시작점 거리 설정 0, U, 또한 직접 설정할 A외부 점대 점 통신 거리이다 .
  4. 외측 제 확대 찾기 U최단 거리에있는 점의 집합 == == (것으로 가정 B컬렉션에 추가) S. 그리고하는 B업데이트 바깥쪽으로 확장, 지적 U값의 집합에서입니다. 후 경우, 규칙을 업데이트 B이하의 점까지의 거리 U레코드의 결과 집합 업데이트가 설정되어 U이 점의 거리.
  5. 때마다 4 단계, 우리는 그릴 수있는 A점으로부터 최단 거리 지점을.
  6. 까지의 4 단계를 반복 U세트가 비어 있거나 목표점이 아닌 U설정 요구는 최단 거리를 계산한다.

도 문제 해결 프로세스로 표현 :

증명

同样以上图为例,我们如何保证第一次选择得到结果A-> B (6)是正确的最优解。
证明:

  • 上述图为无向图,且不存在负权边。
  • 由A出发去其他点,穷举第一条边所有选择,只能为A -> B(6)A -> C(12)A -> D(8)三种。一旦第一条边选择了后两种情况,经过C或是D点再绕回B,由于不存在负权边,那么经过C的路线一定大于A->C(12),经过D的路线A->D(8),因此都会大于A ->B(6)
  • 那么为什么第二次选择只能确定D而非刚更新了最小值的E点。首先基于上一步我们确定了由A出发去D点最短路径第一条边只可能是A->BA->D两种情况,而经过B点再选择第二条边也在上轮计算过了,其与第一条边之和均大于A->D(8),所以能够确定到D的最短路径。而由于D->E的最短路径在第二轮尚不知道,因此无法确定到E的最短路径。
  • 同理,可以确定每一轮的解都是最短路径。

算法实现

public class Dijkstra {

    public static int[] getShortestPath(int[][] graph, int source){
        if(graph == null || graph.length <= source)
            throw new IllegalArgumentException();

        if(graph.length != graph[0].length)
            throw new IllegalArgumentException();

        int n = graph[source].length;
//        String[] route = new String[n];


        //保存结果集
        int[] ret = new int[graph[source].length];
        //保存已确定最短路径的点
        int[] visited = new int[graph[source].length];

        //初始化数据
        Arrays.fill(visited, 0);
        Arrays.fill(ret, Integer.MAX_VALUE);
        ret[source] = 0;

        //进行n次筛选
        for(int i=0; i<n; i++){
            //找出结果集中未visited结果中数据最小的点,为该轮确定的最短路径
            int minValueIndex = findMinValue(ret, visited);
            visited[minValueIndex] = 1;

            //更新通过该点是否有新的最短路径生成
            int[] line = graph[minValueIndex];
            for(int j=0; j<line.length; j++){
                if(visited[j] == 0 &&
                        line[j] != Integer.MAX_VALUE &&
                        line[j] + ret[minValueIndex] <= ret[j]){
                    ret[j] = line[j] + ret[minValueIndex];
                }

            }


        }

        return ret;
    }


    private static int findMinValue(int[] source, int[] visited){
        int ret = 0;
        int minVal = Integer.MAX_VALUE;
        for(int i=0; i<source.length; i++){
            if(visited[i] == 0 && source[i] < minVal){
                ret = i;
                minVal = source[i];
            }

        }
        return ret;
    }

}

上述代码见Github

추천

출처www.cnblogs.com/insaneXs/p/11839564.html