//Dijkstra算法求2点间最短路径,其实这里显示了从起点到所有其他点的最短距离
//存储父节点和距离
class DistPar {
int distance;
int parentVer;
public DistPar(int parentVer, int distance) {
this.distance = distance;
this.parentVer = parentVer;
}
}
// 顶点
class Vertex_2 {
char label;
boolean inTree;
public Vertex_2(char label) {
this.label = label;
inTree = false;
}
}
public class MinDistance {
private final int maxVer;
private final int INFINITY = 100000;// 没有边
private int nvers;// 顶点数
private int curVer;// 当前顶点index
private int nTree;// 树中顶点数
private Vertex_2[] vertex;
private int[][] adjMat;
private DistPar[] spath;
private int startToCur;// 开始到当前距离
public MinDistance(int size) {
maxVer = size;
nvers = 0;
nTree = 0;
vertex = new Vertex_2[maxVer];
adjMat = new int[maxVer][maxVer];
for (int i = 0; i < maxVer; i++)
for (int j = 0; j < maxVer; j++)
adjMat[i][j] = INFINITY;
spath = new DistPar[maxVer];
}
public void addVer(char label) {
vertex[nvers++] = new Vertex_2(label);
}
public void addEdge(int start, int end, int distance) {
adjMat[start][end] = distance;
}
public void path(int index) {
int startTree = index;// 书上直接设置起点为0
vertex[startTree].inTree = true;
nTree = 1;
for (int j = 0; j < nvers; j++) {
int tempDist = adjMat[startTree][j];
spath[j] = new DistPar(startTree, tempDist);
}
while (nTree < nvers) {
int indexMin = getMin();
int minDist = spath[indexMin].distance;
if (minDist == INFINITY) {// 如果都为INFINITY或都在树中了,正常时下面语句也可能会输出
System.out.println("unreachable vertices");
break;
} else {
curVer = indexMin;
startToCur = spath[indexMin].distance;
}
vertex[curVer].inTree = true;
nTree++;
adjust_path();
}
displayPath();
// 重置
nTree = 0;
for (int j = 0; j < nvers; j++)
vertex[j].inTree = false;
}
// 显示距离和起点到终点经过的父节点
private void displayPath() {
for (int j = 0; j < nvers; j++) {
if (spath[j].distance == INFINITY)
System.out.print(" inf");
else
System.out.print(spath[j].distance);
char parent = vertex[spath[j].parentVer].label;
System.out.print("-" + parent + " ");
}
System.out.println();
}
//核心部分
private void adjust_path() {
int column = 0;// 书上为1
while (column < nvers) {
if (vertex[column].inTree) {
column++;
continue;
}
int curToFringe = adjMat[curVer][column];
int startToFringe = curToFringe + startToCur;
int spathDist = spath[column].distance;
if (startToFringe < spathDist) {
spath[column].parentVer = curVer;
spath[column].distance = startToFringe;
}
column++;
}
}
private int getMin() {
int minDist = INFINITY;
int indexMin = 0;
for (int i = 0; i < nvers; i++) {// 书上i从1开始,这2个地方修改下可以从任意顶点开始
if (!vertex[i].inTree && spath[i].distance < minDist) {
minDist = spath[i].distance;
indexMin = i;
}
}
return indexMin;
}
public static void main(String[] args) {
MinDistance min = new MinDistance(20);
min.addVer('A');
min.addVer('B');
min.addVer('C');
min.addVer('D');
min.addVer('E');
min.addEdge(0, 1, 50);
min.addEdge(0, 3, 80);
min.addEdge(1, 2, 60);
min.addEdge(1, 3, 90);
min.addEdge(2, 4, 40);
min.addEdge(3, 2, 20);
min.addEdge(3, 4, 70);
min.addEdge(4, 1, 50);
min.path(0);// inf-A 50-A 100-D 80-A 140-C
}
}