也许最直观的图处理问题就是你常常需要使用某种地图软件或者导航系统来获取从一个地方到另一个地方的路径。我们立即可以得到与之对应的图模型:顶点对应交叉路口,边对应公路,边的权重对应该路段的成本(时间或距离)。如果有单行线,那就意味着还需要考虑加权有向图。在这个模型中,问题很容易就可以被归纳为:

  找到一个顶点到达另一个顶点的成本最小的路径。

前言

  单点最短路径指的就是从源点S到给定的目的顶点V的总权重最小的路径。

  从源点S出发,到所有可达的顶点的路径构成了一棵最短路径树(Shortest Path Tree, SPT)。下边显示了从不同源点出发所构成的最短路径树:

  

  本文用到的加权有向图如下:

  

Dijkstra

边的松驰

  下图展示了两个边的松驰的操作。在第一个例子中,因为distTo[v] + weght(v, w) > distTo[w],所以认为边v->w应该失效;在第二个例子中,distTo[v] + weght(v, w) < distTo[w],所以认识从其他顶点到w比从v到w的路径要长,原其他顶点到w的路径应该失效,v->w有效。

  通过这两个例子,我们知道,松驰操作的思想跟Prim算法的思想是很相似的。

  

  Java代码:

 private void relax(EdgeWeightedDigraph G, int v)
{
for (DirectedEdge e : G.adj(v))
{
int w = e.to();
if (distTo[w] > distTo[v] + e.weight())
{
distTo[w] = distTo[v] + e.weight();
edgeTo[w] = e;
}
}
}

Dijkstra算法

  在《算法》中给出的Java代码如下:

 public class DijkstraSP
{
private DirectedEdge[] edgeTo;
private double[] distTo;
private IndexMinPQ<Double> pq;
public DijkstraSP(EdgeWeightedDigraph G, int s)
{
edgeTo = new DirectedEdge[G.V()];
distTo = new double[G.V()];
pq = new IndexMinPQ<Double>(G.V());
for (int v = 0; v < G.V(); v++)
distTo[v] = Double.POSITIVE_INFINITY;
distTo[s] = 0.0;
pq.insert(s, 0.0);
while (!pq.isEmpty())
relax(G, pq.delMin())
}
private void relax(EdgeWeightedDigraph G, int v)
{
for (DirectedEdge e : G.adj(v))
{
int w = e.to();
if (distTo[w] > distTo[v] + e.weight())
{
distTo[w] = distTo[v] + e.weight();
edgeTo[w] = e;
if (pq.contains(w)) pq.change(w, distTo[w]);
else pq.insert(w, distTo[w]);
}
}
}
public double distTo(int v) // standard client query methods
public boolean hasPathTo(int v) // for SPT implementatations
public Iterable<Edge> pathTo(int v) // (See page 649.)
}

  Dijkstra算法的轨迹如下:

  

  具体代码见Github.

"《算法导论》之‘图’":单点最短路径(有向图)的更多相关文章

  1. 【算法导论】单源最短路径之Bellman-Ford算法

    单源最短路径指的是从一个顶点到其它顶点的具有最小权值的路径.我们之前提到的广度优先搜索算法就是一种无权图上执行的最短路径算法,即在所有的边都具有单位权值的图的一种算法.单源最短路径算法可以解决图中任意 ...

  2. 【算法导论】单源最短路径之Dijkstra算法

    Dijkstra算法解决了有向图上带正权值的单源最短路径问题,其运行时间要比Bellman-Ford算法低,但适用范围比Bellman-Ford算法窄. 迪杰斯特拉提出的按路径长度递增次序来产生源点到 ...

  3. 【算法导论】图的广度优先搜索遍历(BFS)

    图的存储方法:邻接矩阵.邻接表 例如:有一个图如下所示(该图也作为程序的实例): 则上图用邻接矩阵可以表示为: 用邻接表可以表示如下: 邻接矩阵可以很容易的用二维数组表示,下面主要看看怎样构成邻接表: ...

  4. 【算法导论】图的深度优先搜索遍历(DFS)

    关于图的存储在上一篇文章中已经讲述,在这里不在赘述.下面我们介绍图的深度优先搜索遍历(DFS). 深度优先搜索遍历实在访问了顶点vi后,访问vi的一个邻接点vj:访问vj之后,又访问vj的一个邻接点, ...

  5. "《算法导论》之‘图’":深度优先搜索、宽度优先搜索(无向图、有向图)

    本文兼参考自<算法导论>及<算法>. 以前一直不能够理解深度优先搜索和广度优先搜索,总是很怕去碰它们,但经过阅读上边提到的两本书,豁然开朗,马上就能理解得更进一步. 下文将会用 ...

  6. 带权图的最短路径算法(Dijkstra)实现

    一,介绍 本文实现带权图的最短路径算法.给定图中一个顶点,求解该顶点到图中所有其他顶点的最短路径 以及 最短路径的长度.在决定写这篇文章之前,在网上找了很多关于Dijkstra算法实现,但大部分是不带 ...

  7. 算法导论——lec 10 图的基本算法及应用

    搜索一个图是有序地沿着图的边訪问全部定点, 图的搜索算法能够使我们发现非常多图的结构信息, 图的搜索技术是图算法邻域的核心. 一. 图的两种计算机表示 1. 邻接表: 这样的方法表示稀疏图比較简洁紧凑 ...

  8. 图的最短路径---迪杰斯特拉(Dijkstra)算法浅析

    什么是最短路径 在网图和非网图中,最短路径的含义是不一样的.对于非网图没有边上的权值,所谓的最短路径,其实就是指两顶点之间经过的边数最少的路径. 对于网图,最短路径就是指两顶点之间经过的边上权值之和最 ...

  9. C++编程练习(11)----“图的最短路径问题“(Dijkstra算法、Floyd算法)

    1.Dijkstra算法 求一个顶点到其它所有顶点的最短路径,是一种按路径长度递增的次序产生最短路径的算法. 算法思想: 按路径长度递增次序产生算法: 把顶点集合V分成两组: (1)S:已求出的顶点的 ...

随机推荐

  1. Redis集群功能预览

    目前Redis Cluster仍处于Beta版本,Redis 3.0将会加入,在此可以先对其主要功能和原理进行一个预览.参考<Redis Cluster - a pragmatic approa ...

  2. python 如何优雅地退出子进程

    python 如何优雅地退出子进程 主进程产生子进程,子进程进入永久循环模式.当主进程要求子进程退出时,如何能安全地退出子进程呢? 参考一些代码,我写了这个例子.运行之后,用kill pid试试.pi ...

  3. Struts 1之DispatchAction

    DispatchAction是struts 1 的内置通用分发器 import org.apache.struts.actions.DispatchAction; public class UserA ...

  4. 1.关于QT中的Graphics绘图,定时器,动画,将窗口中的内容打印到图片上,打印机,打印预览

     1 新建项目 A  修改pro中的内容如下: HEADERS += \ MyWidget.h SOURCES += \ MyWidget.cpp QT += gui widgets prints ...

  5. Retrofit2.0 ,OkHttp3完美同步持久Cookie实现免登录(二)

    原文出自csdn: http://blog.csdn.net/sk719887916/article/details/51700659: 通过对Retrofit2.0的<Retrofit 2.0 ...

  6. The Chain Of Responsibility (1)

    今天分享一下,设计模式中的责任链模式,其余的不过多叙述. 思路 在正式接触责任连之前,我们可以想象到的应该是一个链,链表?要处理一件事需要一个链似得?其实答案差不多就是这样.设计模式也都是从朴素的思维 ...

  7. linux命令指usermod(管理用户以及权限的命令)

    usermod命令:用来修改用户帐号的各项设定. 示例:usermod -a -G usergroupnewuser 或者usermod -aGusergroup newuser 语法:usermod ...

  8. Java 8新特性探究(二)类型注解和重复注解

    本文将介绍java 8的第二个特性:类型注解. 注解大家都知道,从java5开始加入这一特性,发展到现在已然是遍地开花,在很多框架中得到了广泛的使用,用来简化程序中的配置.那充满争议的类型注解究竟是什 ...

  9. python循环for,range,xrange;while

    >>>range(1,5)#代表从1到5(不包含5) [1,2,3,4] >>>range(1,5,2)#代表从1到5,间隔2(不包含5) [1,3] >&g ...

  10. (NO.00002)iOS游戏精灵战争雏形(六)

    接下来我们给MainScene场景再添加一个精灵,作为敌人. 双击SpriteBuilder中的MainScene.ccb,从控件库拖入一个CCSprite到CCPhysicsNode中,设置精灵帧为 ...