소개
Dijistra
최단 경로 알고리즘의 알고리즘은도 다른 노드들에 하나 개의 노드에서의 최단 거리를 계산하기 위해 사용될 수있다.
당신이 중간 점을 찾을 때까지 주로 발견 층의 아이디어를 통해 중앙 노드에서 바깥쪽으로 확장합니다.
방향성 그래프와 유향 그래프에 적합합니다.
알고리즘
- 우리는 노드를 계산한다고 가정
A
다른 노드 최단 거리를 - 두 세트 (도입
S
,U
) 세트는, 상기S
최단 경로를 나타내는 컬렉션은 결정된 포인트 (최단 거리)이었다U
결정되지 않은 최단 경로의 시점을 나타낸다. 요소의 세트와 유사한A(0)
상기 표현A
대상 점은A
,(0)
최단 경로를 나타냄이 알려져있다0
(비와 직접 통신로∞
표시). - 우선,
S
그것은 단지 시작점 거리 설정0
, U, 또한 직접 설정할A
외부 점대 점 통신 거리이다∞
.
- 외측 제 확대 찾기
U
최단 거리에있는 점의 집합 == == (것으로 가정B
컬렉션에 추가)S
. 그리고하는B
업데이트 바깥쪽으로 확장, 지적U
값의 집합에서입니다. 후 경우, 규칙을 업데이트B
이하의 점까지의 거리U
레코드의 결과 집합 업데이트가 설정되어U
이 점의 거리.
- 때마다 4 단계, 우리는 그릴 수있는
A
점으로부터 최단 거리 지점을.
- 까지의 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->B
和A->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。