Dijkstra算法的Java代码实现
本文借鉴Yngz_Miao作者的Dijkstra算法一文,在实现的过程中,简化部分代码,对自己犯的一些错误和易错点进行注释提醒。希望与遇到相同问题的伙伴分享!
基于邻接矩阵的代码实现:
//图Graph中的方法
public int[] dijkstra(int start){
//构建距离数组保存每次比较后的最短路径
int [] distances = new int [num];
//根据图初始化所有路径,有之间连接则为小的正数,没有直接连接的,按照原来的邻接矩阵,直接赋值为Integer.MAX_VALUE
for(int i = 0;i < num;i++){
distances[i] = weight[start][i];
}
System.out.println(vertexes[start]+"起初到各点之间的直接距离为:"+Arrays.toString(distances));
//构建记录顶点被访问状态
boolean isVisited [] = new boolean [num];
//设置当前开始起点状态为被访问
isVisited[start] = true;
//开始遍历其余所有顶点
for(int i = 0; i < num ; i++){
//记录找到的最短路径顶点的索引。默认-1
int index = -1;
//初始化最小距离
int minDistance = Integer.MAX_VALUE;
//遍历查找距离当前节点最小的距离的顶点。只要有连接,值一定小于Min.此时可以找到了该点,记录
for(int j = 0; j<num; j++){
//如果该顶点状态未访问且两顶点之间距离更短,则更新
if(!isVisited[j] && distances[j] < minDistance){
//记录当前索引方便后续以它为起点,继续遍历
index = j;
//改变最小距离
minDistance = distances[j];
}
}
//!!!!!注意 这一步一定要等上面循环完找到全部路径中最短路径,再判断,
//而不是,上面if成立,就改变其状态。顺序是从最短路径逐个开始建立最短路径数组,而不是字母的顺序
if(index!= -1){
//找到了,就改变其状态
isVisited[index] = true;
}
//更新源点到index索引处的最短路径--实质就是更新之前没有连接的那些顶点,多条路走过去
for(int k= 0; k < num; k++){
//以index为起点,继续向后查找。
//首先必须是未访问过的顶点
if(!isVisited[k]){
//!!!这里的不等于max为前提很关键,不可以省略!!!否则最大Integer+任何一个正数,会发生越界,
//导致运算和的结果为-Integer.Max(-2147483647),那if成立,导致错误
//有直接连接后,如果多条路线的权值和更小,则更新
if( weight[index][k] != Integer.MAX_VALUE && minDistance + weight[index][k] < distances[k]){
distances[k] = minDistance + weight[index][k];
}
}
}
}
return distances;
}
其余图的类和主方法测试如下:
//图的类
class Graph{
int num;//表示顶点个数
char [] vertexes;//表示节点信息
int [][] weight ;//表示边的权重
//传进来一个顶点个数构建图对象
public Graph(int num,char [] vertex,int [][] len){
this.num = num;
vertexes = new char[num];
weight = new int [num][num];
//对数据进行赋值,尽量不要直接引用,会改变传进来的参数,不合适
for (int i = 0; i < num; i++) {
this.vertexes[i] = vertex[i];
for (int j = 0; j < num; j++) {
this.weight[i][j] = len[i][j];
}
}
}
//展示
public void show(){
for(int [] link : weight){
System.out.println(Arrays.toString(link));
}
}
}
主方法测试:
public class DijkstraAlgorithm {
/**
* dijkstra算法求最短路径问题
* 利用广度优先遍历,从开始顶点逐个查找路径赋值给dis[]数组,然后保存
* 如果遇到新的点导致min+weight[index][k] < dis[k] 那就更新
* @param args
*/
public static final int MAX = Integer.MAX_VALUE;
public static void main(String[] args) {
int num = 7;
char [] vertexes = {'A','B','C','D','E','F','G'};
//边的权值,自己对自己边权值为0,非直接连接的权值MAX
int[][] weight = {
{ 0, 5, 7, MAX, MAX, MAX, 2 },
{ 5, 0, MAX, 9, MAX, MAX, 3 },
{ 7, MAX, 0, MAX, 8, MAX, MAX },
{ MAX, 9, MAX, 0, MAX, 4, MAX },
{ MAX, MAX, 8, MAX, 0, 5, 4 },
{ MAX, MAX, MAX, 4, 5, 0, 6 },
{ 2, 3, MAX, MAX, 4, 6, 0 } };
//构建图的实例
Graph graph = new Graph(num, vertexes, weight);
//显示邻接矩阵
// graph.show();
//dijkstra算法获取最短路径--以G点为例测试
int[] distances = graph.dijkstra(6);
for(int i = 0; i < num ; i++){
System.out.print(vertexes[i]+"-"+distances[i]+"\t");
}
}
}
如果大家需要Dijkstra算法介绍等详细内容,请参考Yngz_Miao作者关于此的介绍。
【数据结构】图(最短路径Dijkstra算法)的JAVA代码实现