嘤击长空
如图:
思路:先任意找一个根节点,然后开始循环找连接该点所有边,然后找到权值最小的一项,标记被访问,然后再次循环找除了根节点和被访问过的结点的边,找到权值最小的。具体开注释,非常详细哟。
上代码:
public void shortesPath(int i) {
int n = this.vertexCount(); // 图的结点数
boolean[] vset = new boolean[n]; // 已求出最短路径的顶点集合,初始全为false;
vset[i] = true; // 当前的开始结点为true
int[] dist = new int[n]; // 最短路径的长度
int[] path = new int[n]; // 最短路径终点的前一结点
for (int j = 0; j < n; j++) { // 初始化dist和path
dist[j] = this.weight(i, j);
path[j] = (j != i && dist[j] < MAX_WEIGHT) ? i : -1;
}
for (int j = (i + 1) % n; j != i; j = (j + 1) % n) { // 开始寻找从i到各个结点的最短路径,取余为了使防止出现j比结点数i大的情况
int mindist = MAX_WEIGHT, min = 0; // 定义路径最小值和其下标
for (int k = 0; k < n; k++) { // 开始寻找最小路径
if (!vset[k] && dist[k] < mindist) {// 如果没有访问过并且有路径小于当前路径的最小路径
mindist = dist[k]; // 跟新最小路径和最小路径的下标
min = k;
}
}
if (mindist == MAX_WEIGHT) {// 如果没有其他最短路径则此算法结束。
break;
}
vset[min] = true; // 设置最小结点访问过
for (int k = 0; k < n; k++) {// 更新i到其他结点的路径
if (!vset[k] && this.weight(min, k) < MAX_WEIGHT
&& dist[min] + this.weight(min, k) < dist[k]) {// 如果没有被访问,并且小于初始路径权值,更新路径。
dist[k] = dist[min] + this.weight(min, k); //最小路径+最小路径结点到目的结点的权《=》i直接到目的结点的权。决定是否替换。
path[k] = min;
}
}
}
}