有向图mysql_"《算法导论》之‘图’":单点最短路径(有向图)

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

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

前言

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

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

b9bc33463809509a2da53798c47b016c.png

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

bacb9c435dcb34a35958119cb69742c0.png

Dijkstra

边的松驰

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

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

9b1bfae41e2185add0700d7bcf46fd94.png

Java代码:

1 private void relax(EdgeWeightedDigraph G, intv)2 {3 for(DirectedEdge e : G.adj(v))4 {5 int w =e.to();6 if (distTo[w] > distTo[v] +e.weight())7 {8 distTo[w] = distTo[v] +e.weight();9 edgeTo[w] =e;10 }11 }12 }

Dijkstra算法

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

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 public classDijkstraSP2 {3 privateDirectedEdge[] edgeTo;4 private double[] distTo;5 private IndexMinPQpq;6 public DijkstraSP(EdgeWeightedDigraph G, ints)7 {8 edgeTo = newDirectedEdge[G.V()];9 distTo = new double[G.V()];10 pq = new IndexMinPQ(G.V());11 for (int v = 0; v < G.V(); v++)12 distTo[v] =Double.POSITIVE_INFINITY;13 distTo[s] = 0.0;14 pq.insert(s, 0.0);15 while (!pq.isEmpty())16 relax(G, pq.delMin())17 }18 private void relax(EdgeWeightedDigraph G, intv)19 {20 for(DirectedEdge e : G.adj(v))21 {22 int w =e.to();23 if (distTo[w] > distTo[v] +e.weight())24 {25 distTo[w] = distTo[v] +e.weight();26 edgeTo[w] =e;27 if(pq.contains(w)) pq.change(w, distTo[w]);28 elsepq.insert(w, distTo[w]);29 }30 }31 }32 public double distTo(int v) //standard client query methods

33 public boolean hasPathTo(int v) //for SPT implementatations

34 public Iterable pathTo(int v) //(See page 649.)

35 }

View Code

Dijkstra算法的轨迹如下:

b34cddfd26a8c7af17f5b7f20337f627.png

具体代码见Github.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值