经典算法研究系列:二、Dijkstra 算法初探

news/2024/9/22 4:17:45

经典算法研究系列:二、Dijkstra 算法初探

 

 July   二零一一年一月

======================

本文主要参考:算法导论 第二版、维基百科。

写的不好之处,还望见谅。
本经典算法研究系列文章,永久勘误,永久更新、永久维护。
   July、二零一一年二月十日更新。

------------------------------------

一、A*搜索算法

三、dynamic programming

二、Dijkstra 算法

五(续)、教你透彻了解红黑树

五、红黑树算法的实现与剖析

六、教你从头到尾彻底理解KMP算法

四、BFS和DFS优先搜索算法 

--------------------------------------

 

一、Dijkstra 算法的介绍

Dijkstra 算法,又叫迪科斯彻算法(Dijkstra),
算法解决的是有向图中单个源点到其他顶点的最短路径问题。
举例来说,
如果图中的顶点表示城市,而边上的权重表示著城市间开车行经的距离,
Dijkstra 算法可以用来找到两个城市之间的最短路径。

 

二、Dijkstra 的算法实现

Dijkstra 算法的输入包含了一个有权重的有向图 G,以及G中的一个来源顶点 S。
我们以 V 表示 G 中所有顶点的集合,以 E 表示G 中所有边的集合。
(u, v) 表示从顶点 u 到 v 有路径相连,而边的权重则由权重函数 w: E → [0, ∞] 定义。

因此,w(u, v) 就是从顶点 u 到顶点 v 的非负花费值(cost),边的花费可以想像成两个顶点之间的距离。
任两点间路径的花费值,就是该路径上所有边的花费值总和。

已知有 V 中有顶点 s 及 t,Dijkstra 算法可以找到 s 到 t 的最低花费路径(例如,最短路径)。
这个算法也可以在一个图中,找到从一个顶点 s 到任何其他顶点的最短路径。

好,咱们来看下此算法的具体实现:

Dijkstra 算法的实现一(维基百科):

u := Extract_Min(Q) 在顶点集合 Q 中搜索有最小的 d[u] 值的顶点 u。这个顶点被从集合 Q 中删除并返回给用户。

 1  function Dijkstra(G, w, s)
 2     for each vertex v in V[G]                        // 初始化
 3           d[v] := infinity
 4           previous[v] := undefined
 5     d[s] := 0
 6     S := empty set
 7     Q := set of all vertices
 8     while Q is not an empty set                      // Dijkstra演算法主體
 9           u := Extract_Min(Q)
10           S := S union {u}
11           for each edge (u,v) outgoing from u
12                  if d[v] > d[u] + w(u,v)             // 拓展边(u,v)
13                        d[v] := d[u] + w(u,v)
14                        previous[v] := u

如果我们只对在 st 之间寻找一条最短路径的话,我们可以在第9行添加条件如果满足 u = t 的话终止程序。
现在我们可以通过迭代来回溯出 st 的最短路径

1 s := empty sequence
2 u := t
3 while defined u                                       
4       insert u to the beginning of S
5       u := previous[u]
现在序列 S 就是从 st 的最短路径的顶点集. 

 

Dijkstra 算法的实现二(算法导论):

DIJKSTRA(G, w, s)
1  INITIALIZE-SINGLE-SOURCE(G, s)
S Ø
Q V[G]                                 //V*O(1)
while Q Ø
5      do u EXTRACT-MIN(Q)     //EXTRACT-MIN,V*O(V),V*O(lgV)
6         S S {u}
7         for each vertex v Adj[u]
8             do RELAX(u, v, w)       //松弛技术,E*O(1),E*O(lgV)。

 

因为Dijkstra算法总是在V-S中选择“最轻”或“最近”的顶点插入到集合S中,所以我们说它使用了贪心策略。

(贪心算法会在日后的博文中详细阐述)。

===========================================

二零一一年二月九日更新:
此Dijkstra 算法的最初的时间复杂度为O(V*V+E),源点可达的话,O(V*lgV+E*lgV)=>O(E*lgV)
当是稀疏图的情况时,E=V*V/lgV,算法的时间复杂度可为O(V^2)。

但我们知道,若是斐波那契堆实现优先队列的话,算法时间复杂度,则为O(V*lgV + E)。

 

 

三、Dijkstra 算法的执行速度

我们可以用大O符号将Dijkstra 算法的运行时间表示为边数 m 和顶点数 n 的函数。Dijkstra 算法最简单的实现方法是用一个链表或者数组来存储所有顶点的集合 Q,
所以搜索 Q 中最小元素的运算(Extract-Min(Q))只需要线性搜索 Q 中的所有元素。
这样的话算法的运行时间是 O(E^2)。

对于边数少于 E^2 的稀疏图来说,我们可以用邻接表来更有效的实现迪科斯彻算法。
同时需要将一个二叉堆或者斐波纳契堆用作优先队列来寻找最小的顶点(Extract-Min)。

当用到二叉堆时候,算法所需的时间为O(( V+E )logE),
斐波纳契堆能稍微提高一些性能,让算法运行时间达到O(V+ElogE)。(此处一月十六日修正。)

 
开放最短路径优先(OSPF, Open Shortest Path First)算法是迪科斯彻算法在网络路由中的一个具体实现。
与 Dijkstra 算法不同,Bellman-Ford算法可用于具有负数权值边的图,只要图中不存在总花费为负值且从源点 s 可达的环路即可用此算法(如果有这样的环路,则最短路径不存在,因为沿环路循环多次即可无限制的降低总花费)。

与最短路径问题相关最有名的一个问题是旅行商问题(Traveling salesman problem),此类问题要求找出恰好通过所有标点一次且最终回到原点的最短路径。
然而该问题为NP-完全的;换言之,与最短路径问题不同,旅行商问题不太可能具有多项式时间解法。
如果有已知信息可用来估计某一点到目标点的距离,则可改用A*搜寻算法,以减小最短路径的搜索范围。

=========================================

二零一一年二月九日更新
BFS、DFS、Kruskal、Prim、Dijkstra算法时间复杂度的比较:
一般说来,我们知道,BFS,DFS算法的时间复杂度为O(V+E),
最小生成树算法Kruskal、Prim算法的时间复杂度为O(E*lgV)。

而Prim算法若采用斐波那契堆实现的话,算法时间复杂度为O(E+V*lgV),当|V|<<|E|时,E+V*lgV是一个较大的改进。
//|V|<<|E|,=>O(E+V*lgV) << O(E*lgV),对吧。:D

Dijkstra 算法,斐波纳契堆用作优先队列时,算法时间复杂度为O(V*lgV + E)。
//看到了吧,与Prim算法采用斐波那契堆实现时,的算法时间复杂度是一样的。

所以我们,说,BFS、Prime、Dijkstra 算法是有相似之处的,单从各算法的时间复杂度比较看,就可窥之一二。

 

四、图文解析 Dijkstra 算法

 ok,经过上文有点繁杂的信息,你还并不对此算法了如指掌,清晰透彻。
没关系,咱们来幅图,就好了。请允许我再对此算法的概念阐述下,

Dijkstra算法是典型最短路径算法,用于计算一个节点到其他所有节点的最短路径。
不过,针对的是非负值权边。

主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。
[Dijkstra算法能得出最短路径的最优解,但由于它遍历计算的节点很多,所以效率低。]

ok,请看下图:

如下图,设A为源点,求A到其他各所有一一顶点(B、C、D、E、F)的最短路径。线上所标注为相邻线段之间的距离,即权值。

(注:此图为随意所画,其相邻顶点间的距离与图中的目视长度不能一一对等)

               Dijkstra无向图

 

算法执行步骤如下表

 是不是对此Dijkstra 算法有不错的了解了。那么,此文也完了。:D。 

              ----July、2010年12月24日。平安夜。

 

==============================================

此文,写的实在不怎么样。不过,承蒙大家厚爱,此经典算法研究系列的后续文章,个人觉得写的还行。
所以,还请,各位可关注此算法系列的后续文章。谢谢。

                 二零一一年一月四日。

转载于:https://www.cnblogs.com/v-July-v/archive/2010/12/24/1983708.html

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

Java Excel导出复杂excel表格样式之ExcelUtil工具类

Java Excel导出包括普通导出及复杂表格样式&#xff0c;主要是对于需要进行行列合并的列进行特殊处理&#xff0c;计算清楚起始行&#xff0c;结束行&#xff0c;起始列&#xff0c;结束列。 普通导出可以是所有列&#xff0c;也可以是包含某些列&#xff0c;或者排除某些列&am…

CSS截取字符串,兼容浏览器

今天在经典论坛看到有同学问到CSS截取字符多余省略号代替的求助且要兼容FF... 这个的确是个比较头痛的问题&#xff0c;现在我在的公司都是程序截取显示省略符的。兼容是没问题&#xff0c;但在中文和数学或字母混排时&#xff0c;就会有点小小的视觉缺陷。在程序截取中&#x…

读书笔记2|深度学习入门——基于python的理论与实现

深度学习入门&#xff1a;基于Python的理论与实现》高清中文版.pdf 1. python基础&#xff0c;numpy&#xff0c;matplotlib Batch Normalization、Dropout、Adam 图像识别&#xff0c;自然语言处理&#xff0c;语音识别。 不闻不若闻之&#xff0c;闻之不若见之&#xff0…

Java Feign调用时报错:[400 Bad Request] during [POST] to XXX

feign.FeignException$BadRequest: [400] during [POST] to [http… 主要原因是参数过大 可以采取 调大服务提供者的header参数(微服务较多 不太适用) server:port: 8080max-http-header-size: 102400改为requestBody调用服务&#xff08;分批调用接口多次&#xff09;&am…

[发布] Photoshop 油画效果滤镜

【原创性声明】本滤镜是我采用 PS SDK 开发而成&#xff0c;而滤镜的算法具体是由谁提出的可能不详&#xff0c;我是参考了 FilterExplorer 的源码&#xff08;VC 6&#xff09;&#xff0c;本算法的主要参考来源是该项目中的 Filters.cpp, 作者是 Jason Waltman (18, April, 2…

Java解析省市县树形结构工具类

这篇博客将介绍如何根据6位行政编码&#xff0c;解析出省市县区等。adcode共6位&#xff0c;前俩位省/直辖市/自治区&#xff0c;前4位城市&#xff0c;6位区县&#xff0c;并优雅的树形结构输出省市。 本文只解析了俩层&#xff0c;感兴趣的小伙伴可以自行解析区县。 1.效果…

红外视觉1:近红外与中远红外图像

红外视觉1&#xff1a;近红外与中远红外图像 这篇博客将介绍红外成像的基础知识&#xff0c;包括&#xff1a; 什么是红外图像&#xff1a;近红外与中远/远红外(Near vs Mid-Far Infrared/Far infrared)红外热像仪的类型用途 红外视觉简介&#xff1a;近红外与中远红外图像&…

使用Python,PCA对iris数据集降维2维/3维并进行2D,3D散点图绘制(包括有图例无图例,有标题Label无标题Label)

这篇博客将介绍如何使用Python&#xff0c;PCA对iris数据集降维2&#xff0c;3并进行2D,3D散点图绘制&#xff08;包括有图例&无图例&#xff0c;有标题Label&无标题Label&#xff09;。 着重介绍怎么一次性添加多类型的图例到图表&#xff0c;通过显式获取scatter。 …