漫画:图的 “最短路径” 问题 | 技术头条
戳蓝字“CSDN云计算”关注我们哦!
技术头条:干货、简洁、多维全面。更多云计算精华知识尽在眼前,get要点、solve难题,统统不在话下!
作者:蠢萌的小灰
转自:程序员小灰
————— 第二天 —————
如何遍历呢?
第一层,遍历顶点A:
第二层,遍历A的邻接顶点B和C:
第三层,遍历顶点B的邻接顶点D、E,遍历顶点C的邻接顶点F:
第四层,遍历顶点E的邻接顶点G,也就是目标节点:
由此得出,图中顶点A到G的(第一条)最短路径是A-B-E-G:
换句话说,就是寻找从A到G之间,权值之和最小的路径。
————————————
究竟什么是迪杰斯特拉算法?它是如何寻找图中顶点的最短路径呢?
这个算法的本质,是不断刷新起点与其他各个顶点之间的 “距离表”。
让我们来演示一下迪杰斯特拉的详细过程:
第1步,创建距离表。表中的Key是顶点名称,Value是从起点A到对应顶点的已知最短距离。但是,一开始我们并不知道A到其他顶点的最短距离是多少,Value默认是无限大:
第2步,遍历起点A,找到起点A的邻接顶点B和C。从A到B的距离是5,从A到C的距离是2。把这一信息刷新到距离表当中:
第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。把这一信息刷新到表中:
接下来重复第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。把这一信息刷新到表中:
(在第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。把这一信息刷新到表中:
第9步,从距离表中找到从A出发距离最短的点,也就是顶点E。
第10步,遍历顶点E,找到顶点E的邻接顶点G。从E到G的距离是7,所以A到G的距离是7+7=14。把这一信息刷新到表中:
第11步,从距离表中找到从A出发距离最短的点,也就是顶点F。
第10步,遍历顶点F,找到顶点F的邻接顶点G。从F到G的距离是3,所以A到G的距离是8+3=11,小于距离表中的14。把这一信息刷新到表中:
就这样,除终点以外的全部顶点都已经遍历完毕,距离表中存储的是从起点A到所有顶点的最短距离。显然,从A到G的最短距离是11。(路径:A-B-D-F-G)
按照上面的思路,我们来看一下代码实现:
/**
* Dijkstra最短路径算法
*/
public static Map<Integer, Integer> dijkstra(Graph graph, int startIndex) {
//创建距离表,存储从起点到每一个顶点的临时距离
Map<Integer, Integer> distanceMap = new HashMap<Integer,Integer>();
//记录遍历过的顶点
Set<Integer> accessedSet = new HashSet<Integer> ();
//图的顶点数量
int size = graph.vertexes.length;
//初始化最短路径表,到达每个顶点的路径代价默认为无穷大
for(int i=1; i<size; i++){
distanceMap.put(i, Integer.MAX_VALUE);
}
//遍历起点,刷新距离表
accessedSet.add(0);
List<Edge> edgesFromStart = graph.adj[startIndex];
for(Edge edge : edgesFromStart)
{
distanceMap.put(edge.index, edge.weight);
}
//主循环,重复 遍历最短距离顶点和刷新距离表 的操作
for(int i=1; i<size; i++)
{
//寻找最短距离顶点
int minDistanceFromStart = Integer.MAX_VALUE;
int minDistanceIndex = -1;
for(int j=1; j<size; j++)
{
if(!accessedSet.contains(j) && distanceMap.get(j) < minDistanceFromStart)
{
minDistanceFromStart = distanceMap.get(j);
minDistanceIndex = j;
}
}
if(minDistanceIndex == -1){
break;
}
//遍历顶点,刷新距离表
accessedSet.add(minDistanceIndex);
for(Edge edge : graph.adj[minDistanceIndex])
{
if(accessedSet.contains(edge.index)){
continue;
}
int weight = edge.weight;
int preDistance = distanceMap.get(edge.index);
if(weight != Integer.MAX_VALUE && (minDistanceFromStart+ weight < preDistance))
{
distanceMap.put(edge.index, minDistanceFromStart + weight);
}
}
}
return distanceMap;
}
public static void main(String[] args) {
Graph graph = new Graph(7);
initGraph(graph);
Map<Integer, Integer> distanceMap = dijkstra(graph, 0);
int distance = distanceMap.get(6);
System.out.println(distance);
}
/**
* 图的顶点
*/
private static class Vertex {
String data;
Vertex(String data) {
this.data = data;
}
}
/**
* 图的边
*/
private static class Edge {
int index;
int weight;
Edge(int index, int weight) {
this.index = index;
this.weight = weight;
}
}
/**
* 图
*/
private static class Graph {
private Vertex[] vertexes;
private LinkedList<Edge> adj[];
Graph(int size){
//初始化顶点和邻接矩阵
vertexes = new Vertex[size];
adj = new LinkedList[size];
for(int i=0; i<adj.length; i++){
adj[i] = new LinkedList<Edge>();
}
}
}
private static void initGraph(Graph graph){
graph.vertexes[0] = new Vertex("A");
graph.vertexes[1] = new Vertex("B");
graph.vertexes[2] = new Vertex("C");
graph.vertexes[3] = new Vertex("D");
graph.vertexes[4] = new Vertex("E");
graph.vertexes[5] = new Vertex("F");
graph.vertexes[6] = new Vertex("G");
graph.adj[0].add(new Edge(1, 5));
graph.adj[0].add(new Edge(2, 2));
graph.adj[1].add(new Edge(0, 5));
graph.adj[1].add(new Edge(3, 1));
graph.adj[1].add(new Edge(4, 6));
graph.adj[2].add(new Edge(0, 2));
graph.adj[2].add(new Edge(3, 6));
graph.adj[2].add(new Edge(5, 8));
graph.adj[3].add(new Edge(1, 1));
graph.adj[3].add(new Edge(2, 6));
graph.adj[3].add(new Edge(4, 1));
graph.adj[3].add(new Edge(5, 2));
graph.adj[4].add(new Edge(1, 6));
graph.adj[4].add(new Edge(3, 1));
graph.adj[4].add(new Edge(6, 7));
graph.adj[5].add(new Edge(2, 8));
graph.adj[5].add(new Edge(3, 2));
graph.adj[5].add(new Edge(6, 3));
graph.adj[6].add(new Edge(4, 7));
graph.adj[6].add(new Edge(5, 3));
}
福利
扫描添加小编微信,备注“姓名+公司职位”,加入【云计算学习交流群】,和志同道合的朋友们共同打卡学习!
推荐阅读:
为什么给黑洞拍照需要这么长时间?
V神玩起freestyle! 5位以太坊核心大咖在悉尼的演讲精华全在这了!| 直击EDCON
“重构”黑洞:26岁MIT研究生的新算法 | 人物志
零编程基础的 15 岁少年,仅用 9 个月开发了 9 款 App?!
京东“地震”
程序员 996 再上热搜,黑名单增至 84 家!
真香,朕在看了!
漫画:图的 “最短路径” 问题 | 技术头条相关推荐
- 漫画:如何求图的最短路径? | 技术头条
作者 | 程序员小灰 本文经授权转载自程序员小灰(ID:chengxuyuanxiaohui) ----- 第二天 ----- 小灰的思路如下: 第一步,利用迪杰斯特拉算法的距离表,求出从顶点A出 ...
- 如何在一场面试中展现你对Python的coding能力?| 技术头条
点击上方↑↑↑蓝字关注我们~ 作者 | wLsq 来源 | Python数据科学(ID:PyDataScience) 如果你已经通过了招聘人员的电话面试,那么下面正是该展现你代码能力的时候了.无论是练 ...
- FoveaBox:目标检测新纪元,无Anchor时代来临 | 技术头条
作者 | CV君 转载自我爱计算机视觉(ID:aicvml) 目标检测的任务是"分类"并从图像中"定位"出物体,但长久以来,该领域的工作大多是这样:生成可能包含 ...
- 如何通过结构化智能体完成物理构造任务?| 技术头条
作者 | Victor Bapst, Alvaro Sanchez-Gonzalez,Carl Doersch, Kimberly L. Stachenfel 译者 | Linstancy 编辑 | ...
- 我在旷视研究院做检测 | 技术头条
作者 | 俞刚,旷视研究院Detection组负责人.2014年博士毕业于新加坡南洋理工大学,加入旷视.主要负责检测,分割,跟踪,骨架,动作行为等方面的研究以及算法落地工作.俞刚博士带队参加 2017 ...
- OpenStack网络的下一步原来这么走 | 技术头条
戳蓝字"CSDN云计算"关注我们哦! 技术头条:干货.简洁.多维全面.更多云计算精华知识尽在眼前,get要点.solve难题,统统不在话下! 最新版本的OpenStack Stei ...
- 简便 or 缺陷?Python 内置函数大揭秘!| 技术头条
作者 | 豌豆花下猫 责编 | 胡巍巍 内置函数是 Python 的一大特色,用极简的语法实现很多常用的操作. 它们预先定义在内置命名空间中,开箱即用.所见即所得.Python 被公认是一种新手友好型 ...
- 阿里技术副总裁贾扬清:我对人工智能的一点浅见 | 技术头条
作者 | 贾扬清 本文经授权转自"阿里技术" 责编 | 沭七 [导读]一个月前,阿里巴巴达摩院官宣深度学习框架 Caffe 作者.TensorFlow 核心开发者 -- 贾扬清加盟 ...
- 漫画:数据结构之最短路径 Dijkstra 算法的优化 | 技术头条
作者小灰,本文经授权转载自程序员小灰(ID:chengxuyuanxiaohui). 在<漫画:图的 "最短路径" 问题>一文中小灰介绍了单源最短路径算法 Dijkst ...
最新文章
- 配置MPLS BGP ××× 出现单边的故障
- Linux内存管理之高端内存映射
- isnull pivot server sql_SQLServer行列转换 Pivot UnPivot
- python从入门到精通pdf百度云下载-跟老齐学Python从入门到精通 电子版(pdf格式)...
- synchronized锁的基本用法
- 郑州大学采用计算机,郑州大学计算机系作业
- [VS2005]一个简单的CodeSnippet —— 生成类的构造函数。
- Android魔术(第五弹)—— 一步步实现滑动折叠列表
- JIAVA知识点整理
- 使用工具将SQLServer转MYSQL的方法(连数据)
- 殷浩详解DDD:领域层设计规范
- python在末尾加关闭程序_廖雪峰的Python教程教程-02
- java基础应用_Java基础(应用篇)
- HTTP协议请求类型响应简介
- 怎样看oracle删掉没有,肿么查看以前Oracle卸载干净没
- (原)使用ass字幕文件通过ffmpeg给视频添加字幕的一些研究
- ES分布式架构及底层原理
- 深度学习中评估指标:准确率Accuracy、召回率Recall、精确率Precision、特异度(真阴性率)和误报率、灵敏度(真阳性率)和漏报率、F1、PR、ROC、AUC、Dice系数、IOU
- [地图]常用的地图结构
- 清华大学出版社书评征集图书列表
热门文章
- centos安装mysql5.6系统崩溃_CentOS7安装MySQL5.6冲突总结
- python 分类变量回归_极简Python带你探索分类与回归的奥秘
- 关注!部分高校公布暑假时间,暑假将弹性调整?
- 冲击双一流:燕山大学到底实力如何?
- 北师大计算机组成原理离线作业,北师大网络教育 离线作业 计算机组成原理(一、二、三)...
- IP 数据报首部分析
- mac docker搭建开发环境
- 2016-2017NBU期末考试记录
- 小白科普:Netty有什么用?【转载】
- java多线程笔记补充之	线程控制操作