【数据结构与算法】Dijkstra算法
来源:互联网 发布:数据库课程设计怎么做 编辑:程序博客网 时间:2024/06/05 05:48
基本思想
通过Dijkstra计算图G中的最短路径时,需要指定起点s(即从顶点s开始计算)。
此外,引进两个集合S和U。S的作用是记录已求出最短路径的顶点(以及相应的最短路径长度),而U则是记录还未求出最短路径的顶点(以及该顶点到起点s的距离)。
初始时,S中只有起点s;U中是除s之外的顶点,并且U中顶点的路径是"起点s到该顶点的路径"。然后,从U中找出路径最短的顶点,并将其加入到S中;接着,更新U中的顶点和顶点对应的路径。 然后,再从U中找出路径最短的顶点,并将其加入到S中;接着,更新U中的顶点和顶点对应的路径。 ... 重复该操作,直到遍历完所有顶点。
具体过程
初始状态:S是已计算出最短路径的顶点集合,U是未计算除最短路径的顶点的集合!
第1步:将顶点D加入到S中。
此时,S={D(0)}, U={A(∞),B(∞),C(3),E(4),F(∞),G(∞)}。 注:C(3)表示C到起点D的距离是3。
第2步:将顶点C加入到S中。
上一步操作之后,U中顶点C到起点D的距离最短;因此,将C加入到S中,同时更新U中顶点的距离。以顶点F为例,之前F到D的距离为∞;但是将C加入到S之后,F到D的距离为9=(F,C)+(C,D)。
此时,S={D(0),C(3)}, U={A(∞),B(23),E(4),F(9),G(∞)}。
第3步:将顶点E加入到S中。
上一步操作之后,U中顶点E到起点D的距离最短;因此,将E加入到S中,同时更新U中顶点的距离。还是以顶点F为例,之前F到D的距离为9;但是将E加入到S之后,F到D的距离为6=(F,E)+(E,D)。
此时,S={D(0),C(3),E(4)}, U={A(∞),B(23),F(6),G(12)}。
第4步:将顶点F加入到S中。
此时,S={D(0),C(3),E(4),F(6)}, U={A(22),B(13),G(12)}。
第5步:将顶点G加入到S中。
此时,S={D(0),C(3),E(4),F(6),G(12)}, U={A(22),B(13)}。
第6步:将顶点B加入到S中。
此时,S={D(0),C(3),E(4),F(6),G(12),B(13)}, U={A(22)}。
第7步:将顶点A加入到S中。
此时,S={D(0),C(3),E(4),F(6),G(12),B(13),A(22)}。
此时,起点D到各个顶点的最短距离就计算出来了:A(22) B(13) C(3) D(0) E(4) F(6) G(12)。
代码:
package com.smart.reflect;import java.io.IOException;import java.util.Scanner;public class MatrixUDG { private int mEdgNum; // 边的数量 private char[] mVexs; // 顶点集合 private int[][] mMatrix; // 邻接矩阵 private static final int INF = Integer.MAX_VALUE; // 最大值 /* * 创建图(自己输入数据) */ public MatrixUDG() { // 输入"顶点数"和"边数" System.out.printf("input vertex number: "); int vlen = readInt(); System.out.printf("input edge number: "); int elen = readInt(); if (vlen < 1 || elen < 1 || (elen > (vlen * (vlen - 1)))) { System.out.printf("input error: invalid parameters!\n"); return; } // 初始化"顶点" mVexs = new char[vlen]; for (int i = 0; i < mVexs.length; i++) { System.out.printf("vertex(%d): ", i); mVexs[i] = readChar(); } // 1. 初始化"边"的权值 mEdgNum = elen; mMatrix = new int[vlen][vlen]; for (int i = 0; i < vlen; i++) { for (int j = 0; j < vlen; j++) { if (i == j) mMatrix[i][j] = 0; else mMatrix[i][j] = INF; } } // 2. 初始化"边"的权值: 根据用户的输入进行初始化 for (int i = 0; i < elen; i++) { // 读取边的起始顶点,结束顶点,权值 System.out.printf("edge(%d):", i); char c1 = readChar(); // 读取"起始顶点" char c2 = readChar(); // 读取"结束顶点" int weight = readInt(); // 读取"权值" int p1 = getPosition(c1); int p2 = getPosition(c2); if (p1 == -1 || p2 == -1) { System.out.printf("input error: invalid edge!\n"); return; } mMatrix[p1][p2] = weight; mMatrix[p2][p1] = weight; } } /* * 创建图(用已提供的矩阵) * * 参数说明: * vexs -- 顶点数组 * matrix-- 矩阵(数据) */ public MatrixUDG(char[] vexs, int[][] matrix) { // 初始化"顶点数"和"边数" int vlen = vexs.length; // 初始化"顶点" mVexs = new char[vlen]; for (int i = 0; i < mVexs.length; i++) mVexs[i] = vexs[i]; // 初始化"边" mMatrix = new int[vlen][vlen]; for (int i = 0; i < vlen; i++) for (int j = 0; j < vlen; j++) mMatrix[i][j] = matrix[i][j]; // 统计"边" mEdgNum = 0; for (int i = 0; i < vlen; i++) for (int j = i + 1; j < vlen; j++) if (mMatrix[i][j] != INF) mEdgNum++; } /* * 返回ch位置 */ private int getPosition(char ch) { for (int i = 0; i < mVexs.length; i++) if (mVexs[i] == ch) return i; return -1; } /* * 读取一个输入字符 */ private char readChar() { char ch = '0'; do { try { ch = (char) System.in.read(); } catch (IOException e) { e.printStackTrace(); } } while (!((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))); return ch; } /* * 读取一个输入整数 */ private int readInt() { Scanner scanner = new Scanner(System.in); return scanner.nextInt(); } /* * 打印矩阵队列图 */ public void print() { System.out.printf("Martix Graph:\n"); for (int i = 0; i < mVexs.length; i++) { for (int j = 0; j < mVexs.length; j++) System.out.printf("%10d ", mMatrix[i][j]); System.out.printf("\n"); } } /* * Dijkstra最短路径。 * 即统计图中"顶点vs"到其它各个顶点的最短路径。 * * 参数说明: * vs -- 起始顶点(start vertex)。即计算"顶点vs"到其它顶点的最短路径。 * prev -- 前驱顶点数组。即,prev[i]的值是"顶点vs"到"顶点i"的最短路径所经历的全部顶点中,位于"顶点i"之前的那个顶点。 * dist -- 长度数组。即,dist[i]是"顶点vs"到"顶点i"的最短路径的长度。 * 关键要点: * 1.避免形成回路可以boolean数组进行访问控制,这点和深度遍历、广度遍历是类似的 * 2.贪心 每次选取已经联通的点所能联通边的节点 这和floyd顺序获取节点是最大的不同 */ public void dijkstra(int vs, int[] prev, int[] dist) { // flag[i]=true表示"顶点vs"到"顶点i"的最短路径已成功获取 boolean[] flag = new boolean[mVexs.length]; // 初始化 for (int i = 0; i < mVexs.length; i++) { flag[i] = false; // 顶点i的最短路径还没获取到。 prev[i] = 0; // 顶点i的前驱顶点为0。 dist[i] = mMatrix[vs][i]; // 顶点i的最短路径为"顶点vs"到"顶点i"的权。 } // 对"顶点vs"自身进行初始化 flag[vs] = true; dist[vs] = 0; // 遍历mVexs.length-1次;每次找出一个顶点的最短路径。 int k = 0; for (int i = 0; i < mVexs.length; i++) { // 寻找当前最小的路径; // 即,在未获取最短路径的顶点中,找到离vs最近的顶点(k)。 int min = INF; for (int j = 0; j < mVexs.length; j++) { if (flag[j] == false && dist[j] < min) { min = dist[j]; k = j; } } // 标记"顶点k"为已经获取到最短路径 flag[k] = true; // 修正当前最短路径和前驱顶点 // 即,当已经"顶点k的最短路径"之后,更新"未获取最短路径的顶点的最短路径和前驱顶点"。 for (int j = 0; j < mVexs.length; j++) { int tmp = (mMatrix[k][j] == INF ? INF : (min + mMatrix[k][j])); if (flag[j] == false && (tmp < dist[j])) { dist[j] = tmp; prev[j] = k; } } } // 打印dijkstra最短路径的结果 System.out.printf("dijkstra(%c): \n", mVexs[vs]); for (int i = 0; i < mVexs.length; i++){ System.out.printf("shortest(%c, %c)=%d ", mVexs[vs], mVexs[i], dist[i]); //打印最短路径具体过程 System.out.print( mVexs[i]+" "); int x=prev[i]; while(x!=0){ System.out.print(mVexs[x]+" "); x=prev[x]; } System.out.print(mVexs[vs]+"\n"); } } public static void main(String[] args) { char[] vexs = {'A', 'B', 'C', 'D', 'E', 'F', 'G'}; int matrix[][] = { /*A*//*B*//*C*//*D*//*E*//*F*//*G*/ /*A*/ {0, 12, INF, INF, INF, 16, 14}, /*B*/ {12, 0, 10, INF, INF, 7, INF}, /*C*/ {INF, 10, 0, 3, 5, 6, INF}, /*D*/ {INF, INF, 3, 0, 4, INF, INF}, /*E*/ {INF, INF, 5, 4, 0, 2, 8}, /*F*/ {16, 7, 6, 10000, 2, 0, 9}, /*G*/ {14, INF, INF, INF, 8, 9, 0}}; MatrixUDG pG; // 自定义"图"(输入矩阵队列) //pG = new MatrixUDG(); // 采用已有的"图" pG = new MatrixUDG(vexs, matrix); //pG.print(); // 打印图 int[] prev = new int[pG.mVexs.length]; int[] dist = new int[pG.mVexs.length]; // dijkstra算法获取"第4个顶点"到其它各个顶点的最短距离 pG.dijkstra(3, prev, dist); }}
- 【数据结构与算法】 Dijkstra算法
- 【数据结构与算法】Dijkstra算法
- 算法与数据结构-单源最短路径之Dijkstra
- 数据结构之Dijkstra算法
- 数据结构 Dijkstra(迪杰斯特拉)算法
- 数据结构之Dijkstra算法
- 数据结构 图 Dijkstra算法
- 数据结构与算法12:单源最短路径Dijkstra算法
- 数据结构----dijkstra算法,单源最短路径
- 数据结构:单源最短路径--Dijkstra算法
- [数据结构] 邻接矩阵实现Dijkstra算法
- [数据结构]Dijkstra算法求单源最短路径
- 《数据结构实战》------------------------------------实现Dijkstra算法
- 数据结构:单源最短路径--Dijkstra算法
- Dijkstra算法与Floyd算法
- [数据结构与算法]最短路径—Dijkstra算法和Floyd算法
- 《数据结构与算法分析》最短路径算法--BFS遍历和Dijkstra算法
- 数据结构与算法系列----单源最短路径(Dijkstra算法&Bellman_Ford算法)
- Error:Conflict with dependency 'com.google.code.findbugs:jsr305'
- 初识Hadoop(会飞的大象)
- algorithm 示例
- 矩阵论浅析
- Java内存模型和线程安全
- 【数据结构与算法】Dijkstra算法
- Linux下批量Kill多个进程
- 微服务应用-基于Spring Cloud和Docker构建电影推荐微服务
- 金融直播室开发
- Material Design 学习笔记-- Layout->Structure
- 整环上的进制转换
- C:\WINDOWS\Installer文件夹的安全清理
- @RequestMapping 用法详解之地址映射
- 微服务应用-基于Spring Cloud和Reactor构建网上商店微服务(上)