无向图的最短路径求解算法之——Dijkstra算法
2011-10-18 12:45
369 查看
在准备ACM比赛的过程中,研究了图论中一些算法。首先研究的便是最短路的问题。《离散数学》第四版(清华大学出版社)一书中讲解的Dijkstra算法是我首先研究的源材料。
如何求图中V0到V5的最短路径呢?
java实现的方式如下:
第一步,根据图来建立权值矩阵:
int[][] W = {
{ 0, 1, 4, -1, -1, -1 },
{ 1, 0, 2, 7, 5, -1 },
{ 4, 2, 0, -1, 1, -1 },
{ -1, 7, -1, 0, 3, 2 },
{ -1, 5, 1, 3, 0, 6 },
{ -1, -1, -1, 2, 6, 0 } };(-1表示两边不相邻,权值无限大)
例如:W[0][2]=4 表示点V0到点V2的权值为4
W[0][3]=-1表示点V0与V3不相邻,所以权值无限大。
第二步:对V0标号;V0到其它点的路径得到 distance: {0,1,4,-1,-1,-1}; 找到V0到各点中权值最小的那个点(标号的点除外,-1代表无限大),故得到1即对应的下标1,得到V1;对V1标号,然后更改V0通过V1到其它点的路径得到 distance: { 0, 1, 3, 8, 6, -1};
第三步:找到distance中权值最小的那个点,(标号的点除外)得到V2,对V2标号,然后更改V0通过V1->V2到其它点的路径得到 distance: { 0, 1, 3, 8, 4, -1};
第四步:找到distance中权值最小的那个点,(标号的点除外)得到V4,对V4标号,然后更改V0通过V1->V2到其它点的路径得到 distance: { 0, 1, 3, 7, 4, 10};
第四步:找到distance中权值最小的那个点,(标号的点除外)得到V3,对V3标号,然后更改V0通过V1->V2到其它点的路径得到 distance: { 0, 1, 3, 7, 4, 9};
最后只剩下V5没有被标号,就找到V5了。结束!
源代码如下:
如果需要求无向图各个点的最短距离矩阵,则多次运用dijkstra算法就可以了,代码如下:
如果需要我的学习资料,我非常乐意分享;如果读者能够有所赐教,我甚感荣幸。QQ:810050504(小帅),邮箱是QQ邮箱
如何求图中V0到V5的最短路径呢?
java实现的方式如下:
第一步,根据图来建立权值矩阵:
int[][] W = {
{ 0, 1, 4, -1, -1, -1 },
{ 1, 0, 2, 7, 5, -1 },
{ 4, 2, 0, -1, 1, -1 },
{ -1, 7, -1, 0, 3, 2 },
{ -1, 5, 1, 3, 0, 6 },
{ -1, -1, -1, 2, 6, 0 } };(-1表示两边不相邻,权值无限大)
例如:W[0][2]=4 表示点V0到点V2的权值为4
W[0][3]=-1表示点V0与V3不相邻,所以权值无限大。
第二步:对V0标号;V0到其它点的路径得到 distance: {0,1,4,-1,-1,-1}; 找到V0到各点中权值最小的那个点(标号的点除外,-1代表无限大),故得到1即对应的下标1,得到V1;对V1标号,然后更改V0通过V1到其它点的路径得到 distance: { 0, 1, 3, 8, 6, -1};
第三步:找到distance中权值最小的那个点,(标号的点除外)得到V2,对V2标号,然后更改V0通过V1->V2到其它点的路径得到 distance: { 0, 1, 3, 8, 4, -1};
第四步:找到distance中权值最小的那个点,(标号的点除外)得到V4,对V4标号,然后更改V0通过V1->V2到其它点的路径得到 distance: { 0, 1, 3, 7, 4, 10};
第四步:找到distance中权值最小的那个点,(标号的点除外)得到V3,对V3标号,然后更改V0通过V1->V2到其它点的路径得到 distance: { 0, 1, 3, 7, 4, 9};
最后只剩下V5没有被标号,就找到V5了。结束!
源代码如下:
package com.xh.Dijkstra; //这个算法用来解决无向图中任意两点的最短路径 public class ShortestDistanceOfTwoPoint_V5 { public static int dijkstra(int[][] W1, int start, int end) { boolean[] isLabel = new boolean[W1[0].length];// 是否标号 int[] indexs = new int[W1[0].length];// 所有标号的点的下标集合,以标号的先后顺序进行存储,实际上是一个以数组表示的栈 int i_count = -1;//栈的顶点 int[] distance = W1[start].clone();// v0到各点的最短距离的初始值 int index = start;// 从初始点开始 int presentShortest = 0;//当前临时最短距离 indexs[++i_count] = index;// 把已经标号的下标存入下标集中 isLabel[index] = true; while (i_count<W1[0].length) { // 第一步:标号v0,即w[0][0]找到距离v0最近的点 int min = Integer.MAX_VALUE; for (int i = 0; i < distance.length; i++) { if (!isLabel[i] && distance[i] != -1 && i != index) { // 如果到这个点有边,并且没有被标号 if (distance[i] < min) { min = distance[i]; index = i;// 把下标改为当前下标 } } } if (index == end) {//已经找到当前点了,就结束程序 break; } isLabel[index] = true;//对点进行标号 indexs[++i_count] = index;// 把已经标号的下标存入下标集中 if (W1[indexs[i_count - 1]][index] == -1 || presentShortest + W1[indexs[i_count - 1]][index] > distance[index]) { // 如果两个点没有直接相连,或者两个点的路径大于最短路径 presentShortest = distance[index]; } else { presentShortest += W1[indexs[i_count - 1]][index]; } // 第二步:将distance中的距离加入vi for (int i = 0; i < distance.length; i++) { // 如果vi到那个点有边,则v0到后面点的距离加 if (distance[i] == -1 && W1[index][i] != -1) {// 如果以前不可达,则现在可达了 distance[i] = presentShortest + W1[index][i]; } else if (W1[index][i] != -1 && presentShortest + W1[index][i] < distance[i]) { // 如果以前可达,但现在的路径比以前更短,则更换成更短的路径 distance[i] = presentShortest + W1[index][i]; } } } //如果全部点都遍历完,则distance中存储的是开始点到各个点的最短路径 return distance[end] - distance[start]; } public static void main(String[] args) { // 建立一个权值矩阵 int[][] W1 = { //测试数据1 { 0, 1, 4, -1, -1, -1 }, { 1, 0, 2, 7, 5, -1 }, { 4, 2, 0, -1, 1, -1 }, { -1, 7, -1, 0, 3, 2 }, { -1, 5, 1, 3, 0, 6 }, { -1, -1, -1, 2, 6, 0 } }; int[][] W = { //测试数据2 { 0, 1, 3, 4 }, { 1, 0, 2, -1 }, { 3, 2, 0, 5 }, { 4, -1, 5, 0 } }; System.out.println(dijkstra(W1, 0,4)); } }
如果需要求无向图各个点的最短距离矩阵,则多次运用dijkstra算法就可以了,代码如下:
package com.xh.Dijkstra; //这个程序用来求得一个图的最短路径矩阵 public class ShortestDistance_V4 { public static int dijkstra(int[][] W1, int start, int end) { boolean[] isLabel = new boolean[W1[0].length];// 是否标号 int min = Integer.MAX_VALUE; int[] indexs = new int[W1[0].length];// 所有标号的点的下标集合 int i_count = -1; int index = start;// 从初始点开始 int presentShortest = 0; int[] distance = W1[start].clone();// v0到各点的最短距离的初始值 indexs[++i_count] = index;// 把已经标号的下标存入下标集中 isLabel[index] = true; while (true) { // 第一步:标号v0,即w[0][0]找到距离v0最近的点 min = Integer.MAX_VALUE; for (int i = 0; i < distance.length; i++) { if (!isLabel[i] && distance[i] != -1 && i != index) { // 如果到这个点有边,并且没有被标号 if (distance[i] < min) { min = distance[i]; index = i;// 把下标改为当前下标 } } } if (index == end) { break; } isLabel[index] = true; indexs[++i_count] = index;// 把已经标号的下标存入下标集中 if (W1[indexs[i_count - 1]][index] == -1 || presentShortest + W1[indexs[i_count - 1]][index] > distance[index]) { presentShortest = distance[index]; } else { presentShortest += W1[indexs[i_count - 1]][index]; } // 第二步:奖distance中的距离加入vi for (int i = 0; i < distance.length; i++) { // 如果vi到那个点有边,则v0到后面点的距离加 // 程序到这里是有问题滴! 呵呵 if (distance[i] == -1 && W1[index][i] != -1) {// 如果以前不可达,则现在可达了 distance[i] = presentShortest + W1[index][i]; } else if (W1[index][i] != -1 && presentShortest + W1[index][i] < distance[i]) { // 如果以前可达,但现在的路径比以前更短,则更换成更短的路径 distance[i] = presentShortest + W1[index][i]; } } } return distance[end] - distance[start]; } public static int[][] getShortestPathMatrix(int[][] W) { int[][] SPM = new int[W.length][W.length]; //多次利用dijkstra算法 for (int i = 0; i < W.length; i++) { for (int j = i + 1; j < W.length; j++) { SPM[i][j] =dijkstra(W, i, j); SPM[j][i] = SPM[i][j]; } } return SPM; } public static void main(String[] args) { /* 顶点集:V={v1,v2,……,vn} */ int[][] W = { { 0, 1, 3, 4 }, { 1, 0, 2, -1 }, { 3, 2, 0, 5 }, { 4, -1, 5, 0 } }; int[][] W1 = { { 0, 1, 4, -1, -1, -1 }, { 1, 0, 2, 7, 5, -1 }, { 4, 2, 0, -1, 1, -1 }, { -1, 7, -1, 0, 3, 2 }, { -1, 5, 1, 3, 0, 6 }, { -1, -1, -1, 2, 6, 0 } };// 建立一个权值矩阵 ;// 建立一个权值矩阵 int[][] D = getShortestPathMatrix(W1); //输出最后的结果 for (int i = 0; i < D.length; i++) { for (int j = 0; j < D[i].length; j++) { System.out.print(D[i][j] + " "); } System.out.println(); } } }
如果需要我的学习资料,我非常乐意分享;如果读者能够有所赐教,我甚感荣幸。QQ:810050504(小帅),邮箱是QQ邮箱
相关文章推荐
- 【算法】图的应用之Dijkstra算法--单源最短路径的求解
- 无向图的最短路径求解算法之——Dijkstra算法(三)
- 无向图的最短路径求解算法之——Dijkstra算法【转】
- 无向图的最短路径求解算法之——Dijkstra算法
- 贪婪算法在求解最短路径中的应用(JAVA)--Dijkstra算法
- 无向图的最短路径求解算法之——Dijkstra算法(二)
- 无向图的最短路径求解算法之——Dijkstra算法
- 图论算法之最短路径(Dijkstra算法)
- 最短路径算法——Dijkstra算法
- 图算法 单源最短路径 Dijkstra算法(邻接表/邻接矩阵+优先队列STL)
- Dijkstra算法求解最短路径
- 最短路径算法--DIJKSTRA算法,BELLMANFORD算法,FLOYD算法,JOHNSON算法
- 【算法】图的最短路径(Dijkstra算法)
- 算法储备之Dijkstra算法求单源点最短路径
- (阶段三 dijkstra算法温习1.5)HDU 2680 Choose the best route(使用dijkstra算法求解多源起点的最短路径问题)
- 单源最短路径算法 - Dijkstra算法
- 最短路径算法—Dijkstra算法和BellmanFord算法
- 最短路径算法Dijkstra算法(迪杰斯特拉算法)
- 最短路径基本介绍(2)--Dijkstra算法(单源最短路径算法)
- 最短路径算法-迪杰斯特拉Dijkstra算法