路由算法分为两种:距离矢量算法(DV)和链路状态算法(LS),Dijkstra算法是LS算法的主要表现形式。在路由算法中,Dijkstra算法主体和数据结构与算法课程中的并无二致,只是需要计算源结点到其余所有能够到达结点的路径长度,即把其余所有结点均视为目标结点,并通过表格(数组)对算法过程和结果进行记录。
算法的伪代码如下:
Initialization:
N'= {u}
for all nodes v
if v adjacent to u
then D(v)= c(u,v)
else D(v)= ∞
Loop
find w not in N' such that D(w) is a minimum
/*在集合N'之外找离结点最近的结点w*/
add w to N'
update D(v) for all v adjacent to w and not in N':
D(v)= min( D(v), D(w)+ c(w,v))
until all nodes in N'
/*
C (x,y):节点x到y的链路开销;如果不是直接邻居=∞
D(v):从source到dest的路径开销的当前值
P (v):从源到v路径上的前继节点
N’:已知最小代价路径的节点集合
*/
算法的具体java实现如下:
import java.io.IOException;
import java.lang.System;
import java.util.Scanner;
public class Dijkstra {
public static void main(String[] args) throws IOException {
int i, j;
System.out.println("请输入结点总数目:");
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
String[] name = new String[n]; // 储存结点名称5
int[][] distance = new int[n][n]; // 储存两个点之间的距离,若distance[i][j]为a,则意为从name[i]结点到name[j]结点的距离为a
System.out.println("请输入各结点名称:");
for (i = 0; i < n; i++) { // 若a=65536则表示从name[i]到name[j]不连通
name[i] = scanner.next();
}
System.out.println("请输入各结点之间的距离矩阵:");
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
distance[i][j] = scanner.nextInt();
}
}
int[] alreadyIn = new int[n]; // 表示结点是否已被选中过,若是则为1,否则为0
alreadyIn[0] = 1; // 将源结点置为1,其余结点因为数组为int型自动初始化为0
int[] minDistance = new int[n]; // 储存源结点到各结点的最短路径
int min_position = 0;
// int []index = new int [n];
int index = 0;
int[] path = new int[n];
int[] path_out = new int[n];
for (i = 1; i < n; i++) {
minDistance[i] = distance[0][i];
}
minDistance[0] = 65536;
System.out.println("算法过程如下:");
while (containsAllNodes(alreadyIn, n)) {
int min = 65535;
for (i = 1; i < n; i++) {
if (alreadyIn[i] == 0 && minDistance[i] < min) {
min = minDistance[i];
index = i;
}
}
alreadyIn[index] = 1;
for (i = 0; i < n; i++) {
if (distance[index][i] != 65536 && distance[index][i] != 0 && minDistance[i] > minDistance[index] + distance[index][i]) {
minDistance[i] = minDistance[index] + distance[index][i];
path[i] = index;
}
// minDistance[i] = minDistance[i] < minDistance[index] + distance[index][i] ?
// minDistance[i] : minDistance[index] + distance[index][i];
}
for(i = 1; i < n; i++){
System.out.print(minDistance[i] + " ");
}
System.out.println();
}
for (i = 1; i < n; i++) {
System.out.println("源结点" + name[0] + "到结点" + name[i] + "的最短路径消耗为:" + minDistance[i] + "," + name[i] + "的上一个结点为:" + name[path[i]]);
}
scanner.close();
}
private static boolean containsAllNodes(int[] alreadyIn, int n) {
for (int i = 1; i < n; i++) {
if (alreadyIn[i] == 0)
return true;
}
return false;
}
}
运行:
先输入路由结点的总数目,然后输入名称,最后输入距离矩阵。
该距离矩阵表示的有向图为:
距离矩阵中[i][j]处为65536表示从i到j不连通,为0表示从i到i自身。(没有两个路由直接的距离为0吧?)
输出:
该实现结果简要地给出了算法的计算过程:
并且记录了每一条最短路径目的结点的上一个结点是谁,可以根据这个记录一层一层向上溯源,从而形成一条完整的最短路径。