Djkstra算法-用于求解单源最短路径问题
设有向图如下,求解V0到其余节点的最短距离
流程:
1)记录V0节点到其余节点的路径与距离,初始时均为直达路径
2)选取集合中的最短路径,路径的另一端点为X
3)若V0经由X到其他节点存在一条更短的路径,则用新路径替代
4)如此循环,直到获得V0到其余节点的最短路径为止
- 申请一个节点集合,只包含V0顶点
- 若有N个节点,则希望N-1轮后,所有节点归入集合,图中有7个节点,则6轮后所有节点归入集合
- 申请一个距离集合,用于存储V0到其余节点的最终距离,初始时为邻接矩阵中V0到其余节点的直达距离{-1,13, 8,-1,30,-1,32}
- 第一轮找出从V0出发,取距离集合中的最小距离,将弧另一端节点X加入节点集合
- 第二轮找出从V0出发,将经X到其余节点的距离与原距离集合对比,若更小则替换原距离;选出除了节点已在节点集合内的最小弧,将另一端节点加入节点集合
- 依次类推,直到节点集合满为止
/**
* Djkstra算法,用于求解单源最短路径问题
*/
public static class Djkstra{
public static void main(String[] args) {
int[][] matrix = {
{-1,13, 8,-1,30,-1,32},
{-1,-1,-1,-1,-1, 9, 7},
{-1,-1,-1, 5,-1,-1,-1},
{-1,-1,-1,-1, 6,-1,-1},
{-1,-1,-1,-1,-1, 2,-1},
{-1,-1,-1,-1,-1,-1,17},
{-1,-1,-1,-1,-1,-1,-1}
};
List<Integer> vectors = new ArrayList<>(); //用于存放已归入节点
vectors.add(0);//初始化,初始只有V0节点
int[] finalDis = new int[7]; //用于存放V0到其余节点的最终距离
finalDis = matrix[0];//初始化,初始时最终距离 = 邻接矩阵中V0到其余节点的直达距离
while (vectors.size()!=7){
int minVector = getMinVector(finalDis,vectors); //将距离最短的节点归入节点集合
int minDis = finalDis[minVector]; //到距离最短的节点minVector的距离
//若经由minVector到其他节点产生了一条更短的路径,则用这条路径替换finalDis中V0到该节点的距离
for (int i=0;i<7;i++){
if (vectors.contains(Integer.valueOf(i))){ continue; } //该节点已经在节点集合中,非其他节点,跳过
if (matrix[minVector][i] == -1) { continue; } //经中转节点到该节点无路径,跳过
if (matrix[minVector][i] + minDis < finalDis[i] || finalDis[i] == -1) {
finalDis[i] = matrix[minVector][i] + minDis;
}
}
print(finalDis,vectors); //打印本轮V0到其他节点的最终距离
}
}
public static void print(int[] finalDis,List<Integer> vectors){
System.out.print("本轮V0到其他节点的最终距离为:");
for (int finalDi : finalDis) {
System.out.print(finalDi+",");
}
System.out.println();
System.out.print("节点集合中的节点为:");
for (Integer vector : vectors) {
System.out.print(vector+",");
}
System.out.println();
}
private static int getMinVector(int[] finalDis, List<Integer> vectors) {
int min = Integer.MAX_VALUE;
int minVector = -1;
for (int i = 0;i<finalDis.length;i++){
if (finalDis[i] != -1 && finalDis[i] < min && !vectors.contains(Integer.valueOf(i))){
min = finalDis[i];
minVector = i;
}
}
vectors.add(minVector);
return minVector;
}
}
知识点:
- 时间复杂度为O(|v|2),因为从代码结构可以看书,这是一个嵌套循环
- 如果弧带有负数权值,则Djkstra算法不适用
Floyd算法