本算法的主要思想是:
- 每一次找出源节点到各节点的路径长,取出其中最短的一个,此时到达该节点没有其他最短路径了,然后做上标记,防止下一次访问。
- 找到该路径以后,再更新通过当前节点跳往其他节点的路径,但不标记。
- 直到找到所有最短路径长。
package graph.DijstraAlgorithm;
import java.util.Scanner;
public class DijstraAlgorithm {
public static int Max_Value = 100000;//不能设置为Integer的最大值,防止数组越界
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入图的顶点数和边数:");
int vertex = scanner.nextInt();
int edge = scanner.nextInt();
int[][] martix = new int[vertex][vertex];
//初始化图的关系矩阵
for (int i = 0; i < vertex; i++) {
for (int j = 0; j < vertex; j++) {
martix[i][j] = Max_Value;
}
}
//配置相应的边信息
for (int i = 0; i < edge; i++) {
System.out.println("第"+(i+1)+"条边及其权值:");
int source = scanner.nextInt();
int target = scanner.nextInt();
int weight = scanner.nextInt();
martix[source][target] = weight;
}
System.out.println("请输入出发点的序号(此序号应该大于0,小于"+vertex+":");
int source = scanner.nextInt();
dijstra(source,martix);
}
private static void dijstra(int source, int[][] martix) {
//最短路径集合
int[] shortest = new int[martix.length];
//标记已经找到最短路径
int[] visited = new int[martix.length];
//记录到达各节点最短路径的路径长度
String[] path = new String[martix.length];
for (int i = 0; i < martix.length; i++) {
path[i] = new String(source+"->"+i);
}
for (int i = 1; i < martix.length; i++) {
int min = Integer.MAX_VALUE;
int index = -1;
for (int j = 0; j < martix.length; j++) {
if(visited[j]==0&&martix[source][j]<min){
min = martix[source][j];
index = j;
}
}
//更新到本次遍历过程中的最短路径
visited[index] = 1;
shortest[index] = min;
//更新通过index节点到达其他节点的路径长度
for (int j = 0; j < martix.length; j++) {
if (visited[j]==0&&martix[source][index]+martix[index][j]<martix[source][j]){
martix[source][j] = martix[source][index]+martix[index][j];
path[j] = path[index]+"->"+j;
}
}
}
for (int i = 0; i < path.length; i++) {
if (i!=source){
if(shortest[i]<Max_Value){
System.out.println(source+"->"+i+"的路径为:"+path[i]);
}else {
System.out.println(source+"不能达到"+i);
}
}
}
}
}
- Dijstra算法不支持负权值,因为每一次找到一条最短路径,都会进行标记并且不再修改其值,但是当出现负值时,可能会导致原有的最短路径并不是真正的最短路径,但此时已经对该最短路径进行了标记,无法修改。
- 本算法中使用的节点关系初始化权值为Max_Value,而不是Integer的最大值,是因为计算节点的最短路径时会进行相加,若采用后者则会溢出。
- Dijstra算法适合于求单点最短路径。