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

Posted

篇首语:从困难中战胜出来的人 才是真正的赢家。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 贪婪算法之——拓扑排序相关的知识,希望对你有一定的参考价值。

  一个复杂的工程通常可以分解成一组小任务的集合 完成这些小任务意味着整个工程的完成 例如 汽车装配工程可分解为以下任务 将底盘放上装配线 装轴 将座位装在底盘上 上漆 装刹车 装门等等 任务之间具有先后关系 例如在装轴之前必须先将底板放上装配线 任务的先后顺序可用有向图表示——称为顶点活动( Activity On Vertex AOV)网络 有向图的顶点代表任务 有向边(i j) 表示先后关系 任务j 开始前任务i 必须完成 图 显示了六个任务的工程 边( )表示任务 在任务 开始前完成 同样边( )表示任务 在任务 开始前完成 边( )与( )合起来可知任务 在任务 开始前完成 即前后关系是传递的 由此可知 边( )是多余的 因为边( )和( )已暗示了这种关系

  在很多条件下 任务的执行是连续进行的 例如汽车装配问题或平时购买的标有 需要装配 的消费品(自行车 小孩的秋千装置 割草机等等) 我们可根据所建议的顺序来装配 在由任务建立的有向图中 边( i j)表示在装配序列中任务i 在任务j 的前面 具有这种性质的序列称为拓扑序列(topological orders或topological sequences) 根据任务的有向图建立拓扑序列的过程称为拓扑排序(topological sorting) 图 的任务有向图有多种拓扑序列 其中的三种为 和 序列 就不是拓扑序列 因为在这个序列中任务 在 的前面 而任务有向图中的边为( ) 这种序列与边( )及其他边所指示的序列相矛盾 可用贪婪算法来建立拓扑序列 算法按从左到右的步骤构造拓扑序列 每一步在排好的序列中加入一个顶点 利用如下贪婪准则来选择顶点 从剩下的顶点中 选择顶点w 使得w 不存在这样的入边( v w) 其中顶点v 不在已排好的序列结构中出现 注意到如果加入的顶点w违背了这个准则(即有向图中存在边( v w)且v 不在已构造的序列中) 则无法完成拓扑排序 因为顶点v 必须跟随在顶点w 之后 贪婪算法的伪代码如图 所示 while 循环的每次迭代代表贪婪算法的一个步骤

  现在用贪婪算法来求解图 的有向图 首先从一个空序列V开始 第一步选择V的第一个顶点 此时 在有向图中有两个候选顶点 和 若选择顶点 则序列V = 第一步完成 第二步选择V的第二个顶点 根据贪婪准则可知候选顶点为 和 若选择 则V = 下一步 顶点 是唯一的候选 因此V = 第四步 顶点 是唯一的候选 因此把顶点 加入V 得到V = 在最后两步分别加入顶点 和 得V =

   贪婪算法的正确性

  为保证贪婪算法算的正确性 需要证明 ) 当算法失败时 有向图没有拓扑序列; ) 若算法没有失败 V即是拓扑序列 ) 即是用贪婪准则来选取下一个顶点的直接结果 ) 的证明见定理 它证明了若算法失败 则有向图中有环路 若有向图中包含环qj qj + qk qj 则它没有拓扑序列 因为该序列暗示了qj 一定要在qj 开始前完成

  定理 如果图 算法失败 则有向图含有环路

  证明注意到当失败时| V |<>

   数据结构的选择

  为将图 用C + +代码来实现 必须考虑序列V的描述方法 以及如何找出可加入V的候选顶点 一种高效的实现方法是将序列V用一维数组v 来描述的 用一个栈来保存可加入V的候选顶点 另有一个一维数组I n D e g r e e I n D e g r e e[ j ]表示与顶点j相连的节点i 的数目 其中顶点i不是V中的成员 它们之间的有向图的边表示为( i j) 当I n D e g r e e[ j ]变为 时表示j 成为一个候选节点 序列V初始时为空 I n D e g r e e[ j ]为顶点j 的入度 每次向V中加入一个顶点时 所有与新加入顶点邻接的顶点j 其I n D e g r e e[ j ]减 对于有向图 开始时I n D e g r e e [ : ] = [ ] 由于顶点 和 的I n D e g r e e值为 因此它们是可加入V的候选顶点 由此 顶点 和 首先入栈 每一步 从栈中取出一个顶点将其加入V 同时减去与其邻接的顶点的I n D e g r e e值 若在第一步时从栈中取出顶点 并将其加入V 便得到了v [ ] = 和I n D e g r e e [ : ] = [ ] 由于I n D e g r e e [ ]刚刚变为 因此将顶点 入栈

  程序 给出了相应的C + +代码 这个代码被定义为N e t w o r k的一个成员函数 而且 它对于有无加权的有向图均适用 但若用于无向图(不论其有无加权)将会得到错误的结果 因为拓扑排序是针对有向图来定义的 为解决这个问题 利用同样的模板来定义成员函数AdjacencyGraph AdjacencyWGraph L i n k e d G r a p h和L i n k e d W G r a p h 这些函数可重载N e t w o r k中的函数并可输出错误信息 如果找到拓扑序列 则Topological 函数返回t r u e;若输入的有向图无拓扑序列则返回f a l s e 当找到拓扑序列时 将其返回到v [ :n ]中

   Neork:Topological 的复杂性

  第一和第三个f o r循环的时间开销为(n ) 若使用(耗费)邻接矩阵 则第二个for 循环所用的时间为(n );若使用邻接链表 则所用时间为(n+e) 在两个嵌套的while 循环中 外层循环需执行n次 每次将顶点w 加入到v 中 并初始化内层while 循环 使用邻接矩阵时 内层w h i l e循环对于每个顶点w 需花费(n)的时间;若利用邻接链表 则这个循环需花费dwout 的时间 因此 内层while 循环的时间开销为(n )或(n+e) 所以 若利用邻接矩阵 程序 的时间复杂性为(n ) 若利用邻接链表则为(n+e)

  程序 拓扑排序

  bool Neork::Topological(int v[])

  // 计算有向图中顶点的拓扑次序

  // 如果找到了一个拓扑次序 则返回t r u e 此时 在v [ : n ]中记录拓扑次序

  // 如果不存在拓扑次序 则返回f a l s e

  int n = Ve r t i c e s ( ) ;

  // 计算入度

  int *InDegree = new int [n+ ];

  InitializePos(); // 图遍历器数组

  for (int i = ; i <= n; i++) // 初始化

  InDegree[i] = ;

  for (i = ; i <= n; i++) // 从i 出发的边

  int u = Begin(i);

  while (u)

  I n D e g r e e [ u ] + + ;

  u = NextVe r t e x ( i ) ;

  

  // 把入度为 的顶点压入堆栈

  LinkedStack S;

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

  if (!InDegree[i]) S Add(i);

  // 产生拓扑次序

  i = ; // 数组v 的游标

  while (!S IsEmpty()) // 从堆栈中选择

  int w; // 下一个顶点

  S D e l e t e ( w ) ;

  v[i++] = w;

  int u = Begin(w);

  while (u) // 修改入度

  I n D e g r e e [ u ] ;

  if (!InDegree[u]) S Add(u);

  u = NextVe r t e x ( w ) ;

  

  D e a c t i v a t e P o s ( ) ;

  delete [] InDegree;

  return (i == n);

cha138/Article/program/sjjg/201311/23594

相关参考

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

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

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

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

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

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

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

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

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

  在这个问题中给出有向图G它的每条边都有一个非负的长度(耗费)a[i][j]路径的长度即为此路径所经过的边的长度之和对于给定的源顶点s需找出从它到图中其他任意顶点(称为目的)的最短路径图a给出了一个

知识大全 数据结构与算法之C#插入排序

数据结构与算法之C#插入排序  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  usingSyste

知识大全 贪婪算法思想

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

知识大全 图 - 拓扑排序 (一)

  拓扑排序(TopologicalSort)  对一个有向无环图(DirectedAcyclicGraph简称DAG)G进行拓扑排序是将G中所有顶点排成一个线性序列使得图中任  意一对顶点u和v若∈

知识大全 图 - 拓扑排序 (二)

  无后继的顶点优先拓扑排序方法  思想方法  该方法的每一步均是输出当前无后继(即出度为)的顶点对于一个DAG按此方法输出的序列是逆拓扑次序因此设置一个  栈(或向量)T来保存输出的顶点序列即可得到

知识大全 第 1 章 贪婪算法

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