原理(自己理解的,不当之处希望有人可以指出)
图如上, 以求v0到v8顶点为例
首先求一下v0到各个顶点的距离,得到如下数组
我们的目的就是根据上面的数组确定v0到其他各个顶点的最短距离,这样也就获得了v0到v8的最短距离.
第一个可以确定最短距离的点
从这个数组我们可以知道v0到达v1的最短距离肯定是1,但是v0到v2的最短距离却不一定是5
为什么这么肯定呢??????????????
因为与v0直接连通的点就v1和v2这两个点
那么v0到v1的最近距离要么是v0直接到v1的距离:v0-->v1,要么就是v0-->v2-->[....]-->v1的距离
同理v0到v2的最近距离要么是v0直接到v2的距离:v0-->v2,要么就是v0-->v1-->[....]-->v2的距离
由于v0-->v1的距离小于v0-->v2,因此v0直接到v1的距离为v0到v1的直接距离
而对于v0-->v2的距离和v0-->v1-->[....]-->v2的距离并不能得到确定的判断
由此我们找到了v0到v1的最短距离为1
第二个可以确定最短距离的点
那么接着我们就从v0--->v1这条路继续往下走,会得到下图
由此我们找到了v0到v2的最短距离为4
按照上诉思想,我们就可以找到v0到其他各个点的最短距离,当然假如只是为了找v0到某个点如v4,我们只要是v4这个点的最短距离确定了就可以结束上诉过程.
按照上诉思想我写的代码如下:
package cn.nrsc.graph;
/**
* @author 孙川 ---- 最短路径---迪杰斯塔拉算法(dijkstra)
*/
public class Graph_Dijkstra {
// ----------------------------图的表示方式------------------------
private int vertexSize;// 顶点的数量
private int[] vertexs;// 顶点对应的数组
private int[][] matrix;// 邻接矩阵
private static final int MAX_WEIGHT = 1000;// 代表顶点之间不连通
private boolean[] isVisited; // 顶点是否已经被访问
public Graph_Dijkstra(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;
}
isVisited = new boolean[vertexSize];
}
// ----------------------------图的表示方式------------------------
// 最短距离----迪杰斯塔拉算法 start--->end之间的最短距离
public void dijkstra(int start, int end) {
// 自己到自己的距离为0
if (start == end) {
System.out.println(start + "到" + end + "的最短距离为:" + 0);
return;
}
// 首先计算出start到图中其他各个顶点的距离
int[] distance = new int[vertexSize];
// start到其他各个点的距离
for (int i = 0; i < vertexSize; i++)
distance[i] = matrix[start][i];
// 记录已经确认点的Id,如果是end就可以结束循环了
int targetId = 0;
// 记录start到该点是否为最短距离
boolean[] isMinPath = new boolean[vertexSize];
// 到自身的最短距离肯定获取到了
isMinPath[start] = true;
// 迪杰斯塔拉算法的思想是利用distance数组确认出start到图中任意一个点的最短距离
// 一次只能确认start到一个点的最短距离,并且不知道什么时候会确认了到end点的距离,
// 所以我们需要让他一个点一个点的去确认, 直到end点确认了就可以退出循环了
// 最坏的情况下由start到end需要确认的次数是vertexSize-1次
for (int j = 1; j < vertexSize; j++) { // 外层控制确认的次数---最坏情况下为n-1次
int min = MAX_WEIGHT; // 先假设最小距离为MAX_WEIGHT
// distance数组中的最小值为start到它的最短距离 ----- 这里必须得好好理解一下(看我写的原理部分)
// 找到distance数组中的最小值
for (int k = 0; k < vertexSize; k++) {
if (distance[k] < min && !isMinPath[k]) {
min = distance[k];
targetId = k;
}
}
// 确定了start到targetId的最短距离
System.out.println(start + "到" + targetId + "的最短距离为:" + min);
// 在是否获得最短距离数组中进行标记
isMinPath[targetId] = true;
// 如果targetId = end了就说明找到了start到end的最短距离
if (targetId == end)
break;
// 以min这条路继续往下走,找到start到不确定点更小的距离----循环后,不确定点中的最小值,将可以被确定
for (int w = 0; w < vertexSize; w++)
if (!isMinPath[w] && min + matrix[targetId][w] < distance[w])
distance[w] = min + matrix[targetId][w];
}
// 打印一下--start到各个点的最短距离
// for (int i = 0; i < vertexSize; i++)
// System.out.print(" " + distance[i]);
}
public static void main(String[] args) {
Graph_Dijkstra graph = new Graph_Dijkstra(9);
int[] v0 = { 0, 1, 5, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT };
int[] v1 = { 1, 0, 3, 7, 5, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT };
int[] v2 = { 5, 3, 0, MAX_WEIGHT, 1, 7, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT };
int[] v3 = { MAX_WEIGHT, 7, MAX_WEIGHT, 0, 2, MAX_WEIGHT, 3, MAX_WEIGHT, MAX_WEIGHT };
int[] v4 = { MAX_WEIGHT, 5, 1, 2, 0, 3, 6, 9, MAX_WEIGHT };
int[] v5 = { MAX_WEIGHT, MAX_WEIGHT, 7, MAX_WEIGHT, 3, 0, MAX_WEIGHT, 5, MAX_WEIGHT };
int[] v6 = { MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, 3, 6, MAX_WEIGHT, 0, 2, 7 };
int[] v7 = { MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, 9, 5, 2, 0, 4 };
int[] v8 = { MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, 7, 4, 0 };
graph.matrix[0] = v0;
graph.matrix[1] = v1;
graph.matrix[2] = v2;
graph.matrix[3] = v3;
graph.matrix[4] = v4;
graph.matrix[5] = v5;
graph.matrix[6] = v6;
graph.matrix[7] = v7;
graph.matrix[8] = v8;
graph.dijkstra(0, 8);
System.out.println("---------------------");
graph.dijkstra(8, 0);
}
}