【图论】【最短路径】Floyed算法和Dijkstra算法
最短路径在数据结构的教材上有两种生成算法:Floyed算法和Dijkstra算法
Floyed算法
算法思想:
通过三个for循环,求出各个点距离其他各个点的最短距离。其中,最外层for循环遍历中间节点k,第二第三层循环起点i,终点j;算法思想:如果i节点到k节点的距离 加上 k节点到j节点的距离,那么i节点到j节点的距离就更新为dis[i][k] + dis[k][j],等遍历完所有中间节点,就得到了全局的最短路径。
public void floyed() { for (int k = 1; k <= n; k++) { for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) { if (data[i][j] > data[i][k] + data[k][j]) { data[i][j] = data[i][k] + data[k][j]; } } } } for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) { System.out.println(String.format("%d->%d:%d", i, j, data[i][j])); } } }
Dijkstra算法
算法思想:
找到指定节点距离其他节点的最短距离,也就是说该算法找的只是1个节点的最短距离。先指定一个初始节点x,并标记为已访问,然后初始化改节点距离其他节点的距离,接着找到距离最近的一个节点m,标记为已访问,然后计算经过m做中介,是否缩短了节点x到其他未访问节点的距离,有缩短则更性。即:dis[i] > dis[m]+edge[m][i] 那么dis[i] = dis[m]+edge[m][i] 。
Dijkstra算法的过程和Kruskal算法(最小生成树)有些类似,都在寻找最小的问题,然后更新全局的距离。不过Dijkstra每次找到的是距离最近的点,而Kruskal找到的是最短的边。
public void dijkstra(int x) { int pos = x; int join[] = new int[n + 1]; int pre[] = new int[n + 1]; pre[x] = 0; join[x] = 1; for (int i = 1; i <= n; i++) { // 初始化dis if (join[i] == 0) { dis[i] = data[pos][i]; } } for (int i = 0; i < n - 1; i++) { //除开起始点,需要查找n-1次 int min = max; for (int j = 1; j <= n; j++) { if (join[j] == 0 && dis[j] != 0 && min > dis[j]) { min = dis[j]; pos = j; } } join[pos] = 1; for (int j = 1; j <= n; j++) { if (join[j] == 0 && dis[j] > dis[pos] + data[pos][j]) { dis[j] = dis[pos] + data[pos][j]; pre[j] = pos; // 记录下前置节点,用于输出路径 } } } for (int i = 1; i <= n; i++) { if (i == x) { continue; } System.out.println(String.format("%s -> %s: %s", x, i, dis[i])); } for (int i = 1; i <= n; i++) { int preN = pre[i]; if (preN > 0) { System.out.println(String.format("%d pre node is %d", i, preN)); } else { System.out.println(String.format("%d has no pre node", i)); } } }