知识大全 贪婪算法之——单源最短路径

Posted 路径

篇首语:绝大多数人,在绝大多数时候,都只能靠自己。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 贪婪算法之——单源最短路径相关的知识,希望对你有一定的参考价值。

  在这个问题中 给出有向图G 它的每条边都有一个非负的长度(耗费) a [i ][ j ] 路径的长度即为此路径所经过的边的长度之和 对于给定的源顶点s 需找出从它到图中其他任意顶点(称为目的)的最短路径 图 a 给出了一个具有五个顶点的有向图 各边上的数即为长度 假设源顶点s 为 从顶点 出发的最短路径按路径长度顺序列在图 b 中 每条路径前面的数字为路径的长度

  利用E Dijkstra发明的贪婪算法可以解决最短路径问题 它通过分步方法求出最短路径 每一步产生一个到达新的目的顶点的最短路径 下一步所能达到的目的顶点通过如下贪婪准则选取 在还未产生最短路径的顶点中 选择路径长度最短的目的顶点 也就是说 D i j k s t r a的方法按路径长度顺序产生最短路径

  首先最初产生从s 到它自身的路径 这条路径没有边 其长度为 在贪婪算法的每一步中 产生下一个最短路径 一种方法是在目前已产生的最短路径中加入一条可行的最短的边 结果产生的新路径是原先产生的最短路径加上一条边 这种策略并不总是起作用 另一种方法是在目前产生的每一条最短路径中 考虑加入一条最短的边 再从所有这些边中先选择最短的 这种策略即是D i j k s t r a算法

  可以验证按长度顺序产生最短路径时 下一条最短路径总是由一条已产生的最短路径加上一条边形成 实际上 下一条最短路径总是由已产生的最短路径再扩充一条最短的边得到的 且这条路径所到达的顶点其最短路径还未产生 例如在图 中 b 中第二条路径是第一条路径扩充一条边形成的;第三条路径则是第二条路径扩充一条边;第四条路径是第一条路径扩充一条边;第五条路径是第三条路径扩充一条边

  通过上述观察可用一种简便的方法来存储最短路径 可以利用数组p p [ i ]给出从s 到达i的路径中顶点i 前面的那个顶点 在本例中p [ : ] = [ ] 从s 到顶点i 的路径可反向创建 从i 出发按p[i] p[p[i]] p[p[p[i]]] 的顺序 直到到达顶点s 或 在本例中 如果从i = 开始 则顶点序列为p[i]= p[ ]= p[ ]= =s 因此路径为

  为能方便地按长度递增的顺序产生最短路径 定义d [ i ]为在已产生的最短路径中加入一条最短边的长度 从而使得扩充的路径到达顶点i 最初 仅有从s 到s 的一条长度为 的路径 这时对于每个顶点i d [ i ]等于a [ s ] [ i ](a 是有向图的长度邻接矩阵) 为产生下一条路径 需要选择还未产生最短路径的下一个节点 在这些节点中d值最小的即为下一条路径的终点 当获得一条新的最短路径后 由于新的最短路径可能会产生更小的d值 因此有些顶点的d值可能会发生变化

  综上所述 可以得到图 所示的伪代码 ) 将与s 邻接的所有顶点的p 初始化为s 这个初始化用于记录当前可用的最好信息 也就是说 从s 到i 的最短路径 即是由s到它自身那条路径再扩充一条边得到 当找到更短的路径时 p [ i ]值将被更新 若产生了下一条最短路径 需要根据路径的扩充边来更新d 的值

   ) 初始化d[i ] =a[s] [i ]( ≤i≤n)

  对于邻接于s的所有顶点i 置p[i ] =s 对于其余的顶点置p[i ] = ;

  对于p[i]≠ 的所有顶点建立L表

   ) 若L为空 终止 否则转至 )

   ) 从L中删除d值最小的顶点

   ) 对于与i 邻接的所有还未到达的顶点j 更新d[ j ]值为m i nd[ j ] d[i ] +a[i ][ j ] ;若d[ j ]发生了变化且j 还未

  在L中 则置p[ j ] = 并将j 加入L 转至

  图 最短路径算法的描述

   数据结构的选择

  我们需要为未到达的顶点列表L选择一个数据结构 从L中可以选出d 值最小的顶点 如果L用最小堆(见 节)来维护 则这种选取可在对数时间内完成 由于 ) 的执行次数为O ( n ) 所以所需时间为O ( n l o g n ) 由于扩充一条边产生新的最短路径时 可能使未到达的顶点产生更小的d 值 所以在 ) 中可能需要改变一些d 值 虽然算法中的减操作并不是标准的最小堆操作 但它能在对数时间内完成 由于执行减操作的总次数为 O(有向图中的边数)= O ( n ) 因此执行减操作的总时间为O ( n l o g n )

  若L用无序的链表来维护 则 ) 与 ) 花费的时间为O ( n ) ) 的每次执行需O(|L | ) =O( n )的时间 每次减操作需( )的时间(需要减去d[j] 的值 但链表不用改变) 利用无序链表将图 的伪代码细化为程序 其中使用了C h a i n (见程序 )和C h a i n I t e r a t o r类(见程序 )

  程序 最短路径程序

  template

  void AdjacencyWDigraph ::ShortestPaths(int s T d[] int p[])

  // 寻找从顶点s出发的最短路径 在d中返回最短距离

  // 在p中返回前继顶点

  if (s < || s > n) throw OutOfBounds();

  Chain L; // 路径可到达顶点的列表

  ChainIterator I;

  // 初始化d p L

  for (int i = ; i <= n; i++)

  d[i] = a[s][i];

  if (d[i] == NoEdge) p[i] = ;

  else p[i] = s;

  L I n s e r t ( i ) ;

  

  // 更新d p

  while (!L IsEmpty()) // 寻找具有最小d的顶点v

  int *v = I Initialize(L);

  int *w = I Next();

  while (w)

  if (d[*w] < d[*v]) v = w;

  w = I Next();

  // 从L中删除通向顶点v的下一最短路径并更新d

  int i = *v;

  L D e l e t e ( * v ) ;

  for (int j = ; j <= n; j++)

  if (a[i][j] != NoEdge && (!p[j] ||

  d[j] > d[i] + a[i][j]))

  // 减小d [ j ]

  d[j] = d[i] + a[i][j];

  // 将j加入L

  if (!p[j]) L Insert( j);

  p[j] = i;

  

  

  

  若N o E d g e足够大 使得没有最短路径的长度大于或等于N o E d g e 则最后一个for 循环的i f条件可简化为 if (d[j] > d[i] + a[i][j])) NoEdge 的值应在能使d[j]+a[i][j] 不会产生溢出的范围内

   复杂性分析

cha138/Article/program/sjjg/201311/23592

相关参考

知识大全 贪婪算法之——货箱装船

  这个问题来自例船可以分步装载每步装一个货箱且需要考虑装载哪一个货箱根据这种思想可利用如下贪婪准则从剩下的货箱中选择重量最小的货箱这种选择次序可以保证所选的货箱总重量最小从而可以装载更多的货箱根据这

知识大全 贪婪算法之——最小耗费生成树

  在例及中已考察过这个问题因为具有n个顶点的无向网络G的每个生成树刚好具有n条边所以问题是用某种方法选择n条边使它们形成G的最小生成树至少可以采用三种不同的贪婪策略来选择这n条边这三种求解最小生成树

知识大全 贪婪算法之——拓扑排序

  一个复杂的工程通常可以分解成一组小任务的集合完成这些小任务意味着整个工程的完成例如汽车装配工程可分解为以下任务将底盘放上装配线装轴将座位装在底盘上上漆装刹车装门等等任务之间具有先后关系例如在装轴之

知识大全 贪婪算法之——背包问题

  在/背包问题中需对容量为c的背包进行装载从n个物品中选取装入背包的物品每件物品i的重量为wi价值为pi对于可行的背包装载背包中物品的总重量不能超过背包的容量最佳装载是指所装入的物品价值最高即n?i

知识大全 贪婪算法之——二分覆蓋

  二分图是一个无向图它的n个顶点可二分为集合A和集合B且同一集合中的任意两个顶点在图中无边相连(即任何一条边都是一个顶点在集合A中另一个在集合B中)当且仅当B中的每个顶点至少与A中一个顶点相连时A的

知识大全 图 - 最短路径 (二)

  ()算法基本思想  设S为最短距离已确定的顶点集(看作红点集)VS是最短距离尚未确定的顶点集(看作蓝点集)  ①初始化  初始化时只有源点s的最短距离是已知的(SD(s)=)故红点集S=s蓝点集为

知识大全 数据结构 7.10 各对顶点间的最短路径问题

  希赛教育计算机专业考研专业课辅导招生  希赛教育计算机专业考研专业课辅导视频  希赛教育计算机考研专业课在线测试系统  对有向网按弗洛伊德算法求得各对顶点之间的最短路径的过程cha138

知识大全 贪婪算法思想

  在贪婪算法(greedymethod)中采用逐步构造最优解的方法在每个阶段都作出一个看上去最优的决策(在一定的标准下)决策一旦作出就不可再更改作出贪婪决策的依据称为贪婪准则(greedycrite

知识大全 第 1 章 贪婪算法

  虽然设计一个好的求解算法更像是一门艺术而不像是技术但仍然存在一些行之有效的能够用于解决许多问题的算法设计方法你可以使用这些方法来设计算法并观察这些算法是如何工作的一般情况下为了获得较好的性能必须对

知识大全 数据结构考研分类复习真题 第七章 图[44]

  .求出下图中顶点到其余各顶点的最短路径【厦门大学八(分)】  .试利用Dijkstra算法求下图中从顶点a到其他个顶点间的最短路径写出执行算法过程中各步的状态【东南大学四(分)】 lis