注意:在运用该算法之前你必须得先有一个图。
一、图
图的创建我就......完全是抄袭别人的图了。为了测试效果
package BinaryTreeText;
import java.util.LinkedList;
/**
* 图的创建-->邻接矩阵
*
* */
public class Graph {
private int vertexSize; //顶点数量
private int[] vertexs; // 结点数组(存储每一个结点的编号)
private int[][] matrix; // 邻接矩阵
final int MAX_WEIGHT = 1000; // 不能到达的路的权值
private boolean[] isVisited;
public int getMAX_WEIGHT() {
return MAX_WEIGHT;
}
public int[][] getMatrix() {
return matrix;
}
public void setMatrix(int[][] matrix) {
this.matrix = matrix;
}
public int getVertexSize() {
return vertexSize;
}
public void setVertexSize(int vertexSize) {
this.vertexSize = vertexSize;
}
public void createGraph(Graph graph){
int[] a0 = {0,1,5,graph.MAX_WEIGHT,graph.MAX_WEIGHT,11,graph.MAX_WEIGHT,graph.MAX_WEIGHT,graph.MAX_WEIGHT};
int[] a1 = {1,0,3,7,5,graph.MAX_WEIGHT,graph.MAX_WEIGHT,graph.MAX_WEIGHT,graph.MAX_WEIGHT};
int[] a2 = {5,3,0,graph.MAX_WEIGHT,1,7,graph.MAX_WEIGHT,graph.MAX_WEIGHT,graph.MAX_WEIGHT};
int[] a3 = {graph.MAX_WEIGHT,7,graph.MAX_WEIGHT,0,2,graph.MAX_WEIGHT,3,graph.MAX_WEIGHT,graph.MAX_WEIGHT};
int[] a4 = {graph.MAX_WEIGHT,5,1,2,0,3,6,9,graph.MAX_WEIGHT};
int[] a5 = {graph.MAX_WEIGHT,graph.MAX_WEIGHT,7,graph.MAX_WEIGHT,3,0,graph.MAX_WEIGHT,5,graph.MAX_WEIGHT};
int[] a6 = {graph.MAX_WEIGHT,graph.MAX_WEIGHT,graph.MAX_WEIGHT,3,6,graph.MAX_WEIGHT,0,2,7};
int[] a7 = {graph.MAX_WEIGHT,graph.MAX_WEIGHT,graph.MAX_WEIGHT,graph.MAX_WEIGHT,9,5,2,0,4};
int[] a8 = {graph.MAX_WEIGHT,12,8,21,graph.MAX_WEIGHT,7,graph.MAX_WEIGHT,4,0};
matrix[0] = a0;
matrix[1] = a1;
matrix[2] = a2;
matrix[3] = a3;
matrix[4] = a4;
matrix[5] = a5;
matrix[6] = a6;
matrix[7] = a7;
matrix[8] = a8;
}
public Graph(int vertexSize){
this.vertexSize = vertexSize;
this.matrix = new int[vertexSize][vertexSize];
this.vertexs = new int[vertexSize];
for (int i = 0;i<vertexSize;i++){
vertexs[i] = i; // 表示V0--V4
}
isVisited = new boolean[vertexSize];
}
二、算法核心部分
由于我平时看博客的时候会直接看代码,代码上要是有注释的话,就不用来回上下翻动了。所以我就在代码里面注释的很详细了。在此就不在啰嗦。
但是我要声明的是:单源最短路径就是:一个节点到其余各个节点的距离最短,所以我下面有一个shortTablePath【】的数组,专门来存放最短路径。。。注意:刚开始的时候他只是虚拟的最短路径,最后循环完它才是最终的最短路径。
package BinaryTreeText;
public class Dijstra {
private final static int MAXVEX = 9;
private final static int MAXWEIGHT = 65535;
// 用于存储最短路径的数组
private int shortTablePath[] = new int[MAXVEX];
/**
* 获取一个图的最短路径
*
* */
public void shortesPathDijstra(Graph graph){
// 用来存此路径有没有找到
boolean isgetPath[] = new boolean[MAXVEX];
int min ;
int k = 0 ; // 用来存下标
// 这个for循环是先自己人为规定一个最短路径,比如说我们选第0号节点所能到达的边的权重为最开始的最短路径
for (int j = 0;j < graph.getVertexSize(); j++){
// graph.getMatrix()是得到图的邻接矩阵
shortTablePath[j] = graph.getMatrix()[0][j];
}
// 0号节点到自己的路径肯定是0
shortTablePath[0] = 0;
// 0号节点已经确认
isgetPath[0] = true;
// 因为0号节点已经确认了,所以我们从1号节点开始
//两个 for循环相当于遍历图的邻接矩阵
for (int v = 1; v < graph.getVertexSize();v++){
min = MAXWEIGHT;
for (int w = 0;w <graph.getVertexSize();w++){
// 选择当前权值最小的节点,记录它的下标
//如果这个权值等于min或者大于min的话,它肯定不是最小的权值
// 还有一点要注意的是,你当前选择的结点必须是还没有被确定下来的结点
if (shortTablePath[w]<min && !isgetPath[w]){
k = w;
min = shortTablePath[w];
}
}
// 内层跑完一趟for()之后,k就记录的是最小权重的节点编号
isgetPath[k] = true; //既然我们选出最小的权值了,肯定要标记它已经选好,下次就不用再它了
// 声明一下,这块容易搞混,这个for循环完全是用来循环的,没有别的意思
for (int j = 0; j < graph.getVertexSize();j++){
//如果这个节点还没选,并且min(shortTablePath里面上一层for循环中选出的最小值)+graph.getMatrix()[k][j]
// (第k行,上层for循环选中的最小权值对应的结点编号)< 当前(还没有确定的)最短路径时,我们就可以更新
// 虚拟最短路径数组的值了
//到最后遍历完整个邻接矩阵,虚拟最短路径就不在虚拟了,2333
if (!isgetPath[j] && ( min + graph.getMatrix()[k][j] < shortTablePath[j])){
shortTablePath[j] = min + graph.getMatrix()[k][j];
}
}
}
for (int i = 0;i<shortTablePath.length;i++){
System.out.println("V0到"+i+"的最短路径为"+shortTablePath[i]);
}
}
public static void main(String[] args) {
Graph graph = new Graph(9);
graph.createGraph(graph);
new Dijstra().shortesPathDijstra(graph);
}
}
三、运行结果
V0到V0的最短路径为0
V0到V1的最短路径为1
V0到V2的最短路径为4
V0到V3的最短路径为7
V0到V4的最短路径为5
V0到V5的最短路径为8
V0到V6的最短路径为10
V0到V7的最短路径为12
V0到V8的最短路径为16
到此就这样了。上面的注释是我自己的理解,如果有什么不对的地方,欢迎大佬们指正。