JAVA实现Dijkstra算法求单源最短路径
通过输入如有向图和有图源点的源点,可以输出该源点到其他各点的最短距离,及最短路径。
有向图描述类
package domain;
/*有向图类*/
public class Graph {
public int G_num = 8;
public int edge[][]={
{Integer.MAX_VALUE,Integer.MAX_VALUE,47,Integer.MAX_VALUE,70,24,Integer.MAX_VALUE,Integer.MAX_VALUE},
{Integer.MAX_VALUE,Integer.MAX_VALUE,Integer.MAX_VALUE,31,Integer.MAX_VALUE,Integer.MAX_VALUE,74,79},
{Integer.MAX_VALUE,55,Integer.MAX_VALUE,88,23,Integer.MAX_VALUE,66,Integer.MAX_VALUE},
{Integer.MAX_VALUE,Integer.MAX_VALUE,Integer.MAX_VALUE,Integer.MAX_VALUE,Integer.MAX_VALUE,Integer.MAX_VALUE,Integer.MAX_VALUE,29},
{Integer.MAX_VALUE,31,Integer.MAX_VALUE,Integer.MAX_VALUE,Integer.MAX_VALUE,Integer.MAX_VALUE,42,Integer.MAX_VALUE},
{Integer.MAX_VALUE,Integer.MAX_VALUE,25,120,Integer.MAX_VALUE,Integer.MAX_VALUE,Integer.MAX_VALUE,Integer.MAX_VALUE},
{Integer.MAX_VALUE,Integer.MAX_VALUE,Integer.MAX_VALUE,Integer.MAX_VALUE,Integer.MAX_VALUE,Integer.MAX_VALUE,Integer.MAX_VALUE,66},
{Integer.MAX_VALUE,Integer.MAX_VALUE,Integer.MAX_VALUE,Integer.MAX_VALUE,Integer.MAX_VALUE,Integer.MAX_VALUE,Integer.MAX_VALUE,Integer.MAX_VALUE}};
}
算法实现类
import domain.Graph;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Scanner;
/*实现Dijkstra算法*/
public class Dijkstra {
public static ArrayList<int []> dijkstra(Graph graph, int V){
int[] dist = new int [graph.G_num]; //记录源点到各点的最短距离
int[] s = new int [graph.G_num];//记录以得到最短距离的点,初始皆为0
int[] path = new int [graph.G_num];//记录最短距离的路径,值为该点的上一个点,初始值为-1
int v = V-1; //由于在数组中下标是0开始的,图中而点是从1开始,所以减1
//初始化dist,s,path
for (int i = 0; i <graph.G_num ; i++) {
dist[i] = graph.edge[v][i];
s[i]=0;
if (graph.edge[v][i]<Integer.MAX_VALUE){
path[i] = v;
}else path[i] = -1;
}
s[v] = 1; //将源点加入以遍历的点
for (int i = 0; i <graph.G_num; i++) {
int min = Integer.MAX_VALUE; //每一次的dist中的最小值,初始为无穷大
int min_index=v; //最小值对应的下标
//选出当前dist中的最小值
for (int j = 0; j <graph.G_num ; j++) {
if(s[j]==0&&dist[j]<min){
min = dist[j];
min_index = j;
}
}
s[min_index] = 1;//将该点加入已得到结果的点
for (int k = 0; k < graph.G_num; k++) {
//遍历没有得到最短结果的点,如果其到min_index的距离加上min_index到源点的距离小于源点到k的距离则将更新dist,
if (s[k]==0&&graph.edge[min_index][k]<Integer.MAX_VALUE&&
dist[min_index]+graph.edge[min_index][k]<dist[k]){
dist[k]=dist[min_index]+graph.edge[min_index][k];
path[k]=min_index+1;//由于数组下标由0开始,所以记录路径得加以
}
}
}
ArrayList<int[]> res = new ArrayList<int[]>();//新建一个list集合存储以上三个数组
res.add(dist);//将三个数组存入集合
res.add(s);
res.add(path);
return res;//返回集合
}
/*主方法*/
public static void main(String[] args) {
Graph graph = new Graph(); //创建有向图对象
System.out.println("请输入源点:");
Scanner scanner = new Scanner(System.in);
int point=scanner.nextInt();//源点序号
if (point<0||point>graph.G_num){
//如果源点小于0,或大于图中点的个数抛出异常
throw new RuntimeException("输入的源点序号不在图中");
}
//输入回车结束输入
if (scanner.nextLine().isEmpty()){
scanner.close();
}
//调用dijkstra方法,参数为有向图对象,和源点的序号
ArrayList<int[]> list = Dijkstra.dijkstra(graph, point);
//解析结果输出
resolve_res(point,list);
}
private static void resolve_res(int point,ArrayList<int[]> list) {
int[] dist = list.get(0); //获取最短距离数组
int[] path = list.get(2);//获取最短路径数组
for (int i = 0; i < dist.length ; i++) {
if (i!=point-1){ //当目标点不为源点时
if (dist[i]!=Integer.MAX_VALUE){ //当目标点与源点的距离不为无穷时,即有路径,则解析路径
int j = i;
//由于数组下标从0开始,所以i,代表点i+1,新建一个list,存储点i+1的路径
ArrayList pathi = new ArrayList();
//当该点的不为源点(path[j]!=-1),且上一跳不为源点(path[j]!=point-1)时
while (path[j]!=-1&&path[j]!=point-1){
//将该点加入list
pathi.add(path[j]);
//下标转到上一跳
j = path[j]-1;
}
//将路径翻转
Collections.reverse(pathi);
//将路径添加“-->”转化为可视化更好的字符串
String path_str = null;
if(pathi!=null){ //当点i+1为非源点直接连接点时
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(point);
for (Object o : pathi) {
//遍历路径,给其前面添加“-->”
stringBuilder.append("-->");
stringBuilder.append(o);
}
stringBuilder.append("-->"+(i+1));
//stringBuilder转string
path_str=stringBuilder.toString();
}else {//当i+1为与源点直接连接点时
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(point+"-->"+i);
path_str =stringBuilder.toString();
}
System.out.println(point+"点到"+(i+1)+"的最短距离为:"+dist[i]+", "+"最短路径为"+path_str);
}else System.out.println(point+"点到"+(i+1)+"的最短距离为:"+"∞");//当与源点路径时输出
}
}
}
}
执行结果: