`
v_JULY_v
  • 浏览: 69383 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
文章分类
社区版块
存档分类
最新评论

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

阅读更多

经典算法研究系列:二、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)
2 S Ø
3 Q V[G]//V*O(1)
4 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日。平安夜。

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

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

二零一一年一月四日。

分享到:
评论

相关推荐

    什么是dijkstra算法,Java和Python如何实现dijkstra算法

    dijkstra算法:什么是dijkstra算法,Java和Python如何实现dijkstra算法 dijkstra算法:什么是dijkstra算法,Java和Python如何实现dijkstra算法 dijkstra算法:什么是dijkstra算法,Java和Python如何实现dijkstra算法...

    图论常用算法matlab程序:顺向Dijkstra,逆向Dijkstra,Floyd算法,仿 floyd 算法,顺向强-dijk

    图论常用算法matlab程序:顺向Dijkstra,逆向Dijkstra,Floyd算法,仿 floyd 算法,顺向强—dijk,逆向强—dijkstra算法,生长树算法,Ford—Fulkersen算法

    毕业设计:最短路径算法实现,Dijkstra算法,双向Dijkstra算法,CH算法,SILC算法.zip

    毕业设计:最短路径算法实现,Dijkstra算法,双向Dijkstra算法,CH算法,SILC算法 毕业设计:最短路径算法实现,Dijkstra算法,双向Dijkstra算法,CH算法,SILC算法 毕业设计:最短路径算法实现,Dijkstra算法,双向...

    改进Dijkstra机器人路径规划算法研究.pdf

    改进Dijkstra机器人路径规划算法研究 本研究的主要目标是改进在已知环境地图中的单个陆地移动机器人路径规划求解问题。为了达到这个目标,我们使用数学建模软件仿真,对目前机器人路径规划某些算法领域进行复现,并...

    最短路径算法Dijkstra源代码

    最短路径算法Dijkstra是图论中的一个经典算法,由荷兰计算机科学家艾兹格·迪科斯彻在1956年提出。该算法主要用于寻找带权重的有向或无向图中,从一个特定顶点到其他所有顶点的最短路径。Dijkstra算法的核心思想是...

    Dijkstra算法.zip_dijkstra_dijkstra算法

    Dijkstra算法,由荷兰计算机科学家艾兹格·迪科斯彻在1956年发明,是一种用于寻找图中两点间最短路径的算法。它适用于有向或无向图,且边带有非负权重。这个算法的核心思想是贪心策略,即每次选择当前未访问节点中...

    C# 最短路径:Dijkstra算法

    在计算机科学中,寻找图中两点间的最短路径是一个常见的问题,Dijkstra算法就是解决这类问题的一种高效方法。本文将详细讲解如何使用C#实现Dijkstra算法,以及算法的核心思想。 Dijkstra算法是由荷兰计算机科学家艾...

    基于蚁群算法和Dijkstra算法的二维路径规划

    本文将深入探讨基于蚁群算法(Ant Colony Optimization, ACO)和Dijkstra算法的二维路径规划方法。 首先,我们来理解蚁群算法。这是一种受到自然界蚂蚁寻找食物路径启发的优化算法。在自然界中,蚂蚁通过释放信息...

    MATLAB算法介绍:图论中Dijkstra最短路径计算原理与方法详解

    文章通过一系列步骤具体解析了如何使用标号法求解某一节点到网络其它所有顶点之间的最短路径,并给出了详细的求解实例,帮助读者深入理解算法的工作机制。 适用人群:对数据挖掘、图形算法感兴趣的开发者以及相关...

    最短路径算法dijkstra的matlab实现_dijkstra_最短路径算法_

    最短路径算法是图论中的一个经典问题,用于寻找图中两点之间最短的路径。Dijkstra算法是由荷兰计算机科学家艾兹格·迪科斯彻在1956年提出的一种解决这一问题的有效方法。本篇文章将深入探讨Dijkstra算法的基本原理、...

    Dijkstra最短路算法通用Matlab程序_dijkstra_

    Dijkstra最短路径算法是一种经典的图论算法,用于寻找图中单源最短路径。这个算法由荷兰计算机科学家艾兹格·迪科斯彻在1956年提出,广泛应用于网络路由、地理信息系统和图形界面设计等领域。在这个Matlab程序包中,...

    C语言实现Dijkstra算法

    Dijkstra算法,由荷兰计算机科学家艾兹格·迪科斯彻于1956年提出,是一种用于寻找图中两点间最短路径的算法。在C语言中实现Dijkstra算法,需要理解图的表示方法、优先队列的概念以及如何有效地更新路径信息。以下是...

    蚁群算法+Dijkstra算法=二维路径规划,基于蚁群算法的机器人路径规划,matlab

    本文将深入探讨两种在路径规划中常用的算法:蚁群算法(Ant Colony Optimization, ACO)和Dijkstra算法,并介绍如何在MATLAB环境中结合这两种算法实现二维路径规划。 蚁群算法是一种启发式全局优化算法,灵感来源于...

    十三个经典算法研究与总结、目录+索引

    本文是对十三个经典算法的研究与总结,旨在帮助读者理解和掌握这些重要的算法。这些算法涵盖了不同的领域,包括路径搜索、最短路径、动态规划、图遍历、数据结构、字符串匹配、遗传算法、搜索策略、图像处理、傅里叶...

    Dijkstra_路径规划算法_路径规划_dijkstra算法_dijkstra_源码.zip

    Dijkstra算法是图论中的一个经典算法,由荷兰计算机科学家艾兹格·迪科斯彻在1956年提出,主要用于寻找图中两点间最短路径。在路径规划、网络路由、地理信息系统等领域有着广泛的应用。这个压缩包文件包含了关于...

Global site tag (gtag.js) - Google Analytics