漫画:图的 “最短路径” 问题 | 技术头条

戳蓝字“CSDN云计算”关注我们哦!


640?wx_fmt=jpeg

技术头条:干货、简洁、多维全面。更多云计算精华知识尽在眼前,get要点、solve难题,统统不在话下!

作者:蠢萌的小灰

转自:程序员小灰

640?wx_fmt=jpeg

640?wx_fmt=jpeg



—————  第二天  —————



640?wx_fmt=jpeg

640?wx_fmt=jpeg


640?wx_fmt=jpeg



640?wx_fmt=png

640?wx_fmt=jpeg


640?wx_fmt=jpeg


如何遍历呢?


第一层,遍历顶点A:


640?wx_fmt=png



第二层,遍历A的邻接顶点B和C:


640?wx_fmt=png


第三层,遍历顶点B的邻接顶点D、E,遍历顶点C的邻接顶点F:


640?wx_fmt=png


第四层,遍历顶点E的邻接顶点G,也就是目标节点:


640?wx_fmt=png


由此得出,图中顶点A到G的(第一条)最短路径是A-B-E-G:


640?wx_fmt=png



640?wx_fmt=jpeg


640?wx_fmt=png


换句话说,就是寻找从A到G之间,权值之和最小的路径。



640?wx_fmt=jpeg

640?wx_fmt=jpeg

640?wx_fmt=jpeg


————————————



640?wx_fmt=jpeg

640?wx_fmt=jpeg


640?wx_fmt=jpeg

640?wx_fmt=jpeg

640?wx_fmt=jpeg


640?wx_fmt=jpeg



究竟什么是迪杰斯特拉算法?它是如何寻找图中顶点的最短路径呢?


这个算法的本质,是不断刷新起点与其他各个顶点之间的 “距离表”。


让我们来演示一下迪杰斯特拉的详细过程:


第1步,创建距离表。表中的Key是顶点名称,Value是从起点A到对应顶点的已知最短距离。但是,一开始我们并不知道A到其他顶点的最短距离是多少,Value默认是无限大:


640?wx_fmt=png



第2步,遍历起点A,找到起点A的邻接顶点B和C。从A到B的距离是5,从A到C的距离是2。把这一信息刷新到距离表当中:


640?wx_fmt=png



第3步,从距离表中找到从A出发距离最短的点,也就是顶点C。


第4步,遍历顶点C,找到顶点C的邻接顶点D和F(A已经遍历过,不需要考虑)。从C到D的距离是6,所以A到D的距离是2+6=8;从C到F的距离是8,所以从A到F的距离是2+8=10。把这一信息刷新到表中:


640?wx_fmt=png



接下来重复第3步、第4步所做的操作:


第5步,也就是第3步的重复,从距离表中找到从A出发距离最短的点(C已经遍历过,不需要考虑),也就是顶点B。


第6步,也就是第4步的重复,遍历顶点B,找到顶点B的邻接顶点D和E(A已经遍历过,不需要考虑)。从B到D的距离是1,所以A到D的距离是5+1=6,小于距离表中的8;从B到E的距离是6,所以从A到E的距离是5+6=11。把这一信息刷新到表中:


640?wx_fmt=png



(在第6步,A到D的距离从8刷新到6,可以看出距离表所发挥的作用。距离表通过迭代刷新,用新路径长度取代旧路径长度,最终可以得到从起点到其他顶点的最短距离)


第7步,从距离表中找到从A出发距离最短的点(B和C不用考虑),也就是顶点D。


第8步,遍历顶点D,找到顶点D的邻接顶点E和F。从D到E的距离是1,所以A到E的距离是6+1=7,小于距离表中的11;从D到F的距离是2,所以从A到F的距离是6+2=8,小于距离表中的10。把这一信息刷新到表中:


640?wx_fmt=png



第9步,从距离表中找到从A出发距离最短的点,也就是顶点E。


第10步,遍历顶点E,找到顶点E的邻接顶点G。从E到G的距离是7,所以A到G的距离是7+7=14。把这一信息刷新到表中:


640?wx_fmt=png


第11步,从距离表中找到从A出发距离最短的点,也就是顶点F。


第10步,遍历顶点F,找到顶点F的邻接顶点G。从F到G的距离是3,所以A到G的距离是8+3=11,小于距离表中的14。把这一信息刷新到表中:


640?wx_fmt=png


就这样,除终点以外的全部顶点都已经遍历完毕,距离表中存储的是从起点A到所有顶点的最短距离。显然,从A到G的最短距离是11。(路径:A-B-D-F-G)



按照上面的思路,我们来看一下代码实现:


  1. /**

  2. * Dijkstra最短路径算法

  3. */

  4. public static Map<Integer, Integer> dijkstra(Graph graph, int startIndex) {

  5. //创建距离表,存储从起点到每一个顶点的临时距离

  6. Map<Integer, Integer> distanceMap = new HashMap<Integer,Integer>();

  7. //记录遍历过的顶点

  8. Set<Integer> accessedSet = new HashSet<Integer> ();

  9. //图的顶点数量

  10. int size = graph.vertexes.length;

  11. //初始化最短路径表,到达每个顶点的路径代价默认为无穷大

  12. for(int i=1; i<size; i++){

  13. distanceMap.put(i, Integer.MAX_VALUE);

  14. }

  15. //遍历起点,刷新距离表

  16. accessedSet.add(0);

  17. List<Edge> edgesFromStart = graph.adj[startIndex];

  18. for(Edge edge : edgesFromStart)

  19. {

  20. distanceMap.put(edge.index, edge.weight);

  21. }

  22. //主循环,重复 遍历最短距离顶点和刷新距离表 的操作

  23. for(int i=1; i<size; i++)

  24. {

  25. //寻找最短距离顶点

  26. int minDistanceFromStart = Integer.MAX_VALUE;

  27. int minDistanceIndex = -1;

  28. for(int j=1; j<size; j++)

  29. {

  30. if(!accessedSet.contains(j) && distanceMap.get(j) < minDistanceFromStart)

  31. {

  32. minDistanceFromStart = distanceMap.get(j);

  33. minDistanceIndex = j;

  34. }

  35. }

  36. if(minDistanceIndex == -1){

  37. break;

  38. }

  39. //遍历顶点,刷新距离表

  40. accessedSet.add(minDistanceIndex);

  41. for(Edge edge : graph.adj[minDistanceIndex])

  42. {

  43. if(accessedSet.contains(edge.index)){

  44. continue;

  45. }

  46. int weight = edge.weight;

  47. int preDistance = distanceMap.get(edge.index);

  48. if(weight != Integer.MAX_VALUE && (minDistanceFromStart+ weight < preDistance))

  49. {

  50. distanceMap.put(edge.index, minDistanceFromStart + weight);

  51. }

  52. }

  53. }


  54. return distanceMap;

  55. }


  56. public static void main(String[] args) {

  57. Graph graph = new Graph(7);

  58. initGraph(graph);

  59. Map<Integer, Integer> distanceMap = dijkstra(graph, 0);

  60. int distance = distanceMap.get(6);

  61. System.out.println(distance);

  62. }


  63. /**

  64. * 图的顶点

  65. */

  66. private static class Vertex {

  67. String data;

  68. Vertex(String data) {

  69. this.data = data;

  70. }

  71. }


  72. /**

  73. * 图的边

  74. */

  75. private static class Edge {

  76. int index;

  77. int weight;

  78. Edge(int index, int weight) {

  79. this.index = index;

  80. this.weight = weight;

  81. }

  82. }


  83. /**

  84. * 图

  85. */

  86. private static class Graph {

  87. private Vertex[] vertexes;

  88. private LinkedList<Edge> adj[];


  89. Graph(int size){

  90. //初始化顶点和邻接矩阵

  91. vertexes = new Vertex[size];

  92. adj = new LinkedList[size];

  93. for(int i=0; i<adj.length; i++){

  94. adj[i] = new LinkedList<Edge>();

  95. }

  96. }

  97. }


  98. private static void initGraph(Graph graph){

  99. graph.vertexes[0] = new Vertex("A");

  100. graph.vertexes[1] = new Vertex("B");

  101. graph.vertexes[2] = new Vertex("C");

  102. graph.vertexes[3] = new Vertex("D");

  103. graph.vertexes[4] = new Vertex("E");

  104. graph.vertexes[5] = new Vertex("F");

  105. graph.vertexes[6] = new Vertex("G");


  106. graph.adj[0].add(new Edge(1, 5));

  107. graph.adj[0].add(new Edge(2, 2));

  108. graph.adj[1].add(new Edge(0, 5));

  109. graph.adj[1].add(new Edge(3, 1));

  110. graph.adj[1].add(new Edge(4, 6));

  111. graph.adj[2].add(new Edge(0, 2));

  112. graph.adj[2].add(new Edge(3, 6));

  113. graph.adj[2].add(new Edge(5, 8));

  114. graph.adj[3].add(new Edge(1, 1));

  115. graph.adj[3].add(new Edge(2, 6));

  116. graph.adj[3].add(new Edge(4, 1));

  117. graph.adj[3].add(new Edge(5, 2));

  118. graph.adj[4].add(new Edge(1, 6));

  119. graph.adj[4].add(new Edge(3, 1));

  120. graph.adj[4].add(new Edge(6, 7));

  121. graph.adj[5].add(new Edge(2, 8));

  122. graph.adj[5].add(new Edge(3, 2));

  123. graph.adj[5].add(new Edge(6, 3));

  124. graph.adj[6].add(new Edge(4, 7));

  125. graph.adj[6].add(new Edge(5, 3));

  126. }


640?wx_fmt=jpeg


640?wx_fmt=jpeg


640?wx_fmt=jpeg


640?wx_fmt=png


640?wx_fmt=jpeg


640?wx_fmt=jpeg


640?wx_fmt=png


640?wx_fmt=png


福利

扫描添加小编微信,备注“姓名+公司职位”,加入【云计算学习交流群】,和志同道合的朋友们共同打卡学习!


640?wx_fmt=jpeg


推荐阅读:

  • 为什么给黑洞拍照需要这么长时间?

  • V神玩起freestyle! 5位以太坊核心大咖在悉尼的演讲精华全在这了!| 直击EDCON

  • “重构”黑洞:26岁MIT研究生的新算法 | 人物志

  • 零编程基础的 15 岁少年,仅用 9 个月开发了 9 款 App?

  • 京东“地震”

  • 程序员 996 再上热搜,黑名单增至 84 家!


640?wx_fmt=png真香,朕在看了!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/524137.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux 环境安装并配置Git

Git是一个开源的分布式版本控制系统&#xff0c;用于存储和管理项目的源代码。 一、Linux 环境安装并配置Git 1. 运行命令在线安装Git2. 验证Git是否安装成功3. 对Git进行初始化4. 生成Git的授权证书5. 将Git证书配置到github上&#xff0c;保证Linux服务器和GitHub之间可连通…

OpenGL Windows 搭建环境(MFC版本)

目录 一.简介二.freeglut glew三.glfw glad四.猜你喜欢 零基础 OpenGL ES 学习路线推荐 : OpenGL ES 学习目录 >> OpenGL ES 基础 零基础 OpenGL ES 学习路线推荐 : OpenGL ES 学习目录 >> OpenGL ES 特效 零基础 OpenGL ES 学习路线推荐 : OpenGL ES 学习目录…

Qt在指定区域内拖动窗口

将窗口中的小窗口按住拖动&#xff0c;使其在该窗口中移动。 效果图如下&#xff1a; 鼠标左键按住上图中的彩色窗口&#xff0c;就可以在窗口的客户区中来回拖动窗口。 项目的文件结构如下&#xff1a; 创建基于QWidget的应用程序&#xff0c;main.cpp的程序没有做任何的改变…

昨天,终于拿到了腾讯 offer

戳蓝字“CSDN云计算”关注我们哦&#xff01;技术头条&#xff1a;干货、简洁、多维全面。更多云计算精华知识尽在眼前&#xff0c;get要点、solve难题&#xff0c;统统不在话下&#xff01;作者 | 程序员小吴本文来自程序员小吴的一个读者的投稿&#xff0c;我跟他是在 2 月份…

OpenGL 褐色

目录 一.OpenGL 褐色 1.IOS Object-C 版本1.Windows OpenGL ES 版本2.Windows OpenGL 版本 二.OpenGL 褐色 GLSL Shader三.猜你喜欢 零基础 OpenGL ES 学习路线推荐 : OpenGL ES 学习目录 >> OpenGL ES 基础 零基础 OpenGL ES 学习路线推荐 : OpenGL ES 学习目录 >&…

企业实战(Jenkins+GitLab+SonarQube)_03_Jenkins登录

Jenkins怎样登录&#xff1f;接上一篇Jenkins运行 https://blog.csdn.net/weixin_40816738/article/details/90383686 文章目录1. Windows复制秘钥登录Jenkins2. Linux复制秘钥登录Jenkins1. Windows复制秘钥登录Jenkins 秘钥存放文件的位置(如上图所示)&#xff1a; C:\User…

OpenStack精华问答 | OpenStack 网络中 OpenFlow 规则的作用是什么?

被亲生父母抛弃,被众多大厂拒绝,OpenStack 却依旧坚挺。今天就让我们看看关于OpenStack 的精华问答。1Q&#xff1a;OpenStack 网络中 OpenFlow 规则的作用是什么&#xff1f;A&#xff1a; OpenFlow 规则是一种机制&#xff0c;这种机制定义了一个数据包如何从源到达目的地。O…

企业实战(Jenkins+GitLab+SonarQube)_02_Jenkins运行

Jenkins怎样运行&#xff1f; 文章目录一、Jenkins怎样在Windows运行&#xff1f;1. 找到下载的本地jenkins.war的目录&#xff0c;cmd进入命令行&#xff0c;执行&#xff1a;2. jenkins启动成功后&#xff0c;浏览器访问&#xff1a;localhost:8080二、Jenkins怎样在Linux运行…

Windows OpenGL ES 图像褐色

目录 一.OpenGL ES 图像褐色 1.原始图片2.效果演示 二.OpenGL ES 图像褐色源码下载三.猜你喜欢 零基础 OpenGL ES 学习路线推荐 : OpenGL ES 学习目录 >> OpenGL ES 基础 零基础 OpenGL ES 学习路线推荐 : OpenGL ES 学习目录 >> OpenGL ES 特效 零基础 OpenGL E…

要闻君说:国内首个5G电话由中国移动在京被打通!360公司转让奇安信股权;腾讯宣布开源三大开发工具 ,紧追技术共享步伐;...

关注并标星星CSDN云计算极客头条&#xff1a;速递、最新、绝对有料。这里有企业新动、这里有业界要闻&#xff0c;打起十二分精神&#xff0c;紧跟fashion你可以的&#xff01;每周三次&#xff0c;打卡即read更快、更全了解泛云圈精彩newsgo go go OPPO技术开放日第三期&#…

qt编译器5.12.3怎么一次性删除所有的断点

自己尝试出来的一个可以一次性删除所有断点的方法&#xff0c;可能还有其它方法&#xff0c;知者望以告知。 方法&#xff1a; 在debug模式下&#xff0c;进行调试运行&#xff0c;此时会出现调试的箭头&#xff0c;方框之类的一栏&#xff0c;如下图&#xff0c;在横向紧挨着的…

Linux操作系统需要做的准备

Linux操作系统需要做的准备 1. 确定IP地址2. 确认登录用户名密码3. 查看/启动ssh服务4. 确认可以远程连接5. 确认防火墙处于关闭状态 1. 确定IP地址 ifconfig2. 确认登录用户名密码 账号&#xff1a;root 秘钥&#xff1a;1234563. 查看/启动ssh服务 检查ssh服务是否启动 …

Windows OpenGL 图像褐色

目录 一.OpenGL 图像褐色 1.原始图片2.效果演示 二.OpenGL 图像褐色源码下载三.猜你喜欢 零基础 OpenGL ES 学习路线推荐 : OpenGL ES 学习目录 >> OpenGL ES 基础 零基础 OpenGL ES 学习路线推荐 : OpenGL ES 学习目录 >> OpenGL ES 特效 零基础 OpenGL ES 学习…

Qt线程写日志

之前没有考虑写日志时采用单独的线程&#xff0c;而是将写日志的部分放在了主线程中实现&#xff0c;后面发现当程序输出的日志信息过多&#xff0c;程序长时间运行后会造成主线程的运行性能降低。故尝试创建一个单独的线程用来写日志。 此程序有一个弊端&#xff0c;运行时没有…

京解之才——2019年技术盘点微服务篇(三)| 程序员硬核评测

戳蓝字“CSDN云计算”关注我们哦&#xff01;程序员硬核测评&#xff1a;客观、高效、不说软话。无论是技术质量、性能水平&#xff0c;还是工具筛选&#xff0c;一测便知&#xff01;过去几年来&#xff0c;“微服务架构”方兴未艾&#xff0c;尽管这种架构风格没有确切的定义…

Linux环境安装并配置Maven

一、Linux环境安装并配置Maven 1. 进入官网下载Tomat安装包2. 解压安装Tomcat3. 配置可执行权限4. 配置可执行端口&#xff08;避免端口冲突&#xff09;5. 验证Tomcat是否可以正常启动和停止 1. 进入Maven官网复制下载地址下载maven maven官网&#xff1a;http://maven.apach…

OpenGL 色阶

目录 一.OpenGL 色阶 1.Windows OpenGL ES 版本2.Windows OpenGL 版本 二.OpenGL 色阶 GLSL Shader三.猜你喜欢 零基础 OpenGL ES 学习路线推荐 : OpenGL ES 学习目录 >> OpenGL ES 基础 零基础 OpenGL ES 学习路线推荐 : OpenGL ES 学习目录 >> OpenGL ES 特效 …

Qt中全局变量的使用

一般在项目中想要定义一个变量可以被多个类进行访问&#xff0c;此时就可以定义全局变量。习惯上会将项目中所有类都用到的变量&#xff0c;集中定义在一个头文件中&#xff0c;使用时只需包含此头文件。但是对于我这样基础不牢靠的人&#xff0c;就犯了一个错误&#xff0c;而…

强推!2019年最火的容器、K8S和DevOps入门都在这了

戳蓝字“CSDN云计算”关注我们哦&#xff01;技术头条&#xff1a;干货、简洁、多维全面。更多云计算精华知识尽在眼前&#xff0c;get要点、solve难题&#xff0c;统统不在话下&#xff01;作者&#xff1a; Pasca来源&#xff1a;蛋蛋团&#xff08;ID&#xff1a;dandan_tua…

Tomcat10 下载和配置 Linux 环境

文章目录1. 下载Tomat2. 复制链接地址3. 下载4. 解压Tomcat5. 赋予权限6. 启动tomcat7. 监控日志8. linux防火墙9. 浏览器验证1. 下载Tomat tomcat官网&#xff1a;https://tomcat.apache.org/download-10.cgi 2. 复制链接地址 3. 下载 wget https://downloads.apache.org/t…