Dijkstra算法用于解决单源最短路径问题;是贪婪算法的最好的例子。
在上述有向图中,要计算从点1到达其余各点的最短路径。其中两点之间的有向箭头表示从起点到终点的距离,例:0~2之间的箭头表示从0到2的距离为30,从2到0是不可达的。
这里我们使用邻接矩阵data[][]来存储点到点之间的距离,data[3][4]表示3~4的路径,-1表示不可达;
{{ 0, -1, 10, -1, 30, 100},
{-1, 0, 5, -1, -1, -1},
{-1, -1, 0, 50, -1, -1},
{-1, -1, -1, 0, -1, 10},
{-1, -1, -1, 20, 0, 60},
{-1, -1, -1, -1, -1, 0}}
定义一个dis数组表示各点到起点的最短路径,在初始时,起点到各点的距离默认为无穷大(代码中通过Integer.MAX_VALUE)表示;
定义一个loc表示当前的节点;
Dijkstra算法的思路:
代码实现
public class Dijkstra {
public static int[][] data = {
{ 0, -1, 10, -1, 30, 100},
{-1, 0, 5, -1, -1, -1},
{-1, -1, 0, 50, -1, -1},
{-1, -1, -1, 0, -1, 10},
{-1, -1, -1, 20, 0, 60},
{-1, -1, -1, -1, -1, 0}
};
private static class Distance implements Comparable<Distance> {
int num;
int distance = Integer.MAX_VALUE;
List<Integer> path = new ArrayList<>();
boolean mark = false;
public Distance(int num) {
this.num = num;
}
@Override
public String toString() {
return "Distance{" +
"num=" + num +
", distance=" + distance +
", path=" + path +
'}';
}
@Override
public int compareTo(Distance o) {
if (o == null) {
return 1;
}
return Integer.compare(distance, o.distance);
}
}
private static List<Distance> dis = new ArrayList<>();
private static PriorityQueue<Distance> queue = new PriorityQueue<>();
public static void initDis() {
for (int i = 0; i < 6; i++) {
dis.add(new Distance(i));
}
}
public static void dijkstra(int startIndex) {
if (startIndex < 0 || startIndex >= dis.size()) {
return;
}
Distance loc = dis.get(startIndex);
loc.distance = 0;
while (loc != null) {
loc.mark = true;
loc.path.add(loc.num);
System.out.println(loc.toString());
// 更新其他未被标记的点到起点的最短距离
for (Distance tem: dis) {
if (tem.mark) {
continue;
}
// 如果loc到tem可达,且距离小于上一个次判断的距离
if (data[loc.num][tem.num] != -1 && tem.distance > loc.distance + data[loc.num][tem.num]) {
tem.distance = loc.distance + data[loc.num][tem.num];
tem.path.clear();
tem.path.addAll(loc.path);
}
queue.add(tem);
}
loc = queue.poll();
queue.clear();
}
}
public static void main(String[] args) {
initDis();
dijkstra(0);
}
}