图的拓扑排序(转)

一、概述

  对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若<u,v> ∈E(G),则u在线性序列中出现在v之前。
    通常,这样的线性序列称为满足拓扑次序(TopoiSicai Order)的序列,简称拓扑序列
注意:
    ①若将图中顶点按拓扑次序排成一行,则图中所有的有向边均是从左指向右的。
    ②若图中存在有向环,则不可能使顶点满足拓扑次序。
    ③一个DAG的拓扑序列通常表示某种方案切实可行。
    【例】一本书的作者将书本中的各章节学习作为顶点,各章节的先学后修关系作为边,构成一个有向图。按有向图的拓扑次序安排章节,才能保证读者在学习某章节时,其预备知识已在前面的章节里介绍过。
    ④一个DAG可能有多个拓扑序列。
    【例】对图G9进行拓扑排序,至少可得到如下的两个(实际远不止两个)拓扑序列:C0,C1,C2,C4,C3,C5,C7,C8,C6和C0,C7,C9,C1,C4,C2,C3,C6,C5
        
  ⑤当有向图中存在有向环时,拓扑序列不存在
  【例】下面(a)图中的有向环重排后如(b)所示,有向边<v3,vl>和其它边反向。若有向图被用来表示某项工程实施方案或某项工作计划,则找不到该图的拓扑序列(即含有向环),就意味着该方案或计划是不可行的。
        
二、无前趋的顶点优先的拓扑排序方法  

  该方法的每一步总是输出当前无前趋(即人度为零)的顶点,其抽象算法可描述为:
        NonPreFirstTopSort(G){//优先输出无前趋的顶点
            while(G中有人度为0的顶点)do{
             从G中选择一个人度为0的顶点v且输出之;
             从G中删去v及其所有出边;
             }
            if(输出的顶点数目<|V(G)|)
                 //若此条件不成立,则表示所有顶点均已输出,排序成功。
             Error("G中存在有向环,排序失败!");
         }
注意:
     无前趋的顶点优先的拓扑排序算法在具体存储结构下,为便于考察每个顶点的人度,可保存各顶点当前的人度。为避免每次选入度为0的顶点时扫描整个存储空间,可设一个栈或队列暂存所有入度为零的顶点:
     在开始排序前,扫描对应的存储空间,将人度为零的顶点均入栈(队)。以后每次选人度为零的顶点时,只需做出栈(队)操作即可。

三、无后继的顶点优先拓扑排序方法  

1、思想方法
     该方法的每一步均是输出当前无后继(即出度为0)的顶点。对于一个DAG,按此方法输出的序列是逆拓扑次序。因此设置一个栈(或向量)T来保存输出的顶点序列,即可得到拓扑序列。若T是栈,则每当输出顶点时,只需做人栈操作,排序完成时将栈中顶点依次出栈即可得拓扑序列。若T是向量,则将输出的顶点从T[n-1]开始依次从后往前存放,即可保证T中存储的顶点是拓扑序列。
2、抽象算法描述
  算法的抽象描述为:
      NonSuccFirstTopSort(G){//优先输出无后继的顶点
        while(G中有出度为0的顶点)do {
         从G中选一出度为0的顶点v且输出v;
         从G中删去v及v的所有人边
         }
        if(输出的顶点数目<|V(G)|)
             Error("G中存在有向环,排序失败!");
       }
3、算法求精
     在对该算法求精时,可用逆邻接表作为G的存储结构。设置一个向量outdegree[0..n-1]或在逆邻接表的顶点表结点中增加1个出度域来保存各顶点当前的出度;设置一个栈或队列来暂存所有出度为零的顶点。除了增加一个栈或向量T来保存输出的顶点序列外,该算法完全类似于NonPreFirstTopSort。

四、利用深度优先遍历对DAG拓扑排序  

  当从某顶点v出发的DFS搜索完成时,v的所有后继必定均已被访问过(想像它们均已被删除),此时的v相当于是无后继的顶点,因此在DFS算法返回之前输出顶点v即可得到 DAG的逆拓扑序列。
    其中第一个输出的顶点必是无后继(出度为0)的顶点,它应是拓扑序列的最后一个顶点。若希望得到的不是逆拓扑序列,同样可增加T来保存输出的顶点。若假设T是栈,并在DFSTraverse算法的开始处将T初始化,
    利用DFS求拓扑序列的抽象算法可描述为:
      void DFSTopSort(G,i,T){
        //在DisTraverse中调用此算法,i是搜索的出发点,T是栈
        int j;
        visited[i]=TRUE; //访问i
        for(所有i的邻接点j)//即<i,j>∈E(G)
          if(!visited[j])
           DFSTopSort(G,j,T);
           //以上语句完全类似于DFS算法
          Push(&T,i); //从i出发的搜索已完成,输出i
        }
    只要将深度优先遍历算法DFSTraverse中对DFS的调用改为对DFSTopSort的调用,即可求得拓扑序列T。其具体算法不难从上述抽象算法求精后得到。
    若G是一个DAG,则用DFS遍历实现的拓扑排序与NonSuccFirstTopSort算法完全类似;但若C中存在有向环,则前者不能正常工作。

*************************************************************************

dfs实现拓扑排序 函数(算法竞赛入门经典)

E(u,v)

int c[maxn];

int topo[maxn],t;

bool dfs(int u)

{

c[u]=-1;      //开始访问该顶点

for(int v=0;v<n;v++)

{

if(G[u][v]==1)

{

if(c[v]<0) return false;   //c[v]=-1代表正在访问该定点(即递归调用dfs(u)正在帧栈中,尚未返回)

else if(!c[v] && !dfs(v))   return false;   //(c[v]==0 && dfs(v)==false即当前顶点没有后即顶点时,

//开始返回 (结束))

}

}

c[u]=1;      //访问结束

topo[--t]=u;

return true;

}

bool toposort()

{

t=n;

memset(c,0,sizeof(c));

for(int u=0;u<n;u++)

if(!c[u]) if(!dfs())  return false;

return ture;

}

转自:http://blog.csdn.net/liwen_7/article/details/7298736

时间: 2024-10-13 12:39:31

图的拓扑排序(转)的相关文章

java实现AOV图的拓扑排序

拓扑排序作为图的应用,了解拓扑排序必须首先了解AOV图. AOV网表示一个有向图中顶点,用弧表示顶点之间的优先关系.如下图所示,在AOV网中,若从顶点vi到顶点vj之间存在一条有向路径,则称顶点vi为顶点vj的前驱,顶点vj为顶点vi的后继.注意,AOV图不能有回路,否则会将序列陷入死循环,称为死锁. 进行拓扑排序,一般步骤如下: <1>在AOV网中选择一个入度为0的顶点 <2>在AOV网中删除此顶点及其相连的有向边 <3>重复步骤<1>和<2>

DAG图的拓扑排序 python

在DAG中DFS中顶点的出栈顺序即逆拓扑序. def topological_sort( graph ): is_visit = dict( ( node, False ) for node in graph ) li = [] def dfs( graph, start_node ): for end_node in graph[start_node]: if not is_visit[end_node]: is_visit[end_node] = True dfs( graph, end_n

有向无环图(DAG)拓扑排序的两种方法

如下图的DAG: 第一种: (1)从AOV网中选择一个没有前驱的顶点并且输出它: (2)从AOV网中删除该顶点,并且上去所有该顶点为尾的弧: (3)重复上述两步,直到全部顶点都被输出,或者AOV网中不存在没有前驱的顶点. 第二种: 使用深度优先搜索(DFS),并标记每一个节点的第一次访问(pre)和最后一次访问时间(post),最后post的逆序就是DAG的拓扑排序,其实也是节点在进行DFS搜索时,出栈的逆序就是拓扑排序. 拓扑序列的结果有: (1) c++,高等数学,离散数学,数据结构,概率论

图的拓扑排序

定义: 图的拓扑排序是对有向无环图来说的,无向图和有环图没有拓扑排序,或者说不存在拓扑排序,对于一个有向无环图G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若图G存在边< u, v >,则u在线性序列中出现在v之前.对一个有向无环图进行拓扑排序产生的线性序列称为满足拓扑次序的序列.一个有向无环图可以表示某种动作或者方案,或者状态,而有向无环图的拓扑序列通常表示某种某案切实可行或者各个成员之间的某种关系. 举个栗子,看上面那个图,v1v2v3v4v5v6v7v8是

图的邻接表表示与无环图的拓扑排序

一.  图的最常用的表示方法是邻接矩阵和邻接表. 1,邻接矩阵 邻接矩阵其实就是一个二维数组,对于每条边<u,v>,我们就令A[u][v] = 1,如果图为有权图,我们也可以令A[u][v]等于该权,这么表示的优点是非常简单,但是它的空间需求很大,如果图是稠密的,邻接矩阵是合适的表示方法,如果图是稀疏的,那这种方法就太浪费空间了,下面给出图的邻接矩阵表示例子. 2 邻接表 邻接表是图的常用储存结构之一.邻接表由表头结点和表结点两部分组成,其中图中每个顶点均对应一个存储在数组中的表头结点.如下图

图的拓扑排序、关键路径、最短路径算法 -- C++实现

一:拓扑排序 对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边(u,v)∈E(G),则u在线性序列中出现在v之前.通常,这样的线性序列称为满足拓扑次序(Topological Order)的序列,简称拓扑序列. 拓扑排序就是要找到入度为0的顶点,并依次压栈.首先将栈顶顶点输出,删除以此顶点为弧尾的顶点,并更新其他顶点的入度.若入度为0,则继续压栈.更新完毕继续出栈,直至栈空.元素出栈并输出

【图】拓扑排序

参考CSDN拓扑排序的原理及Java实现 拓扑排序C++实现 拓扑排序百度百科 若不是上了学堂在线的数据结构课程,我估计今后不做技术的话,都接触不到图的拓扑排序这个概念了.先是看了百度百科的解释,拓扑排序现实中的应用是选课,即某些课程需要一些先修课程的学习后才适合上.比如数据结构的学习,是离散数学.编程语言,后者是前者的先修课程. 拓扑排序定义:将有向无环图DAG中的顶点以线性方式进行排序.即对于任何连接自顶点u到顶点v的有向边uv,在最后的排序结果中,顶点u总是在顶点v的前面. 1.创建图:

[CF825E] Minimal Labels(反向建图,拓扑排序)

题目链接:http://codeforces.com/problemset/problem/825/E 题意:给一个有向图,求一个排列,这个排列是每一个点的序号,使得序号对应的点的排序符合拓扑序并且这个排列字典序最小. 直接跑字典序最小的拓扑排序是不行的,因为那样只是确保点的字典序而非这个排列的字典序,比如这个数据: 10 15 2 反过来考虑,点号大的入度为0的点一定排在后面,这个位置确定了.但是点好小的入度为0的未必一定排在前面,因为这个点之前可能有入度不为0,但是与此点无关的点在前面,按题

算法学习 - 图的拓扑排序

拓扑排序 拓扑排序是对有向无圈图的顶点的一种排序,使得如果存在一条从Vi到Vj的路径,那么排序中Vj一定出现在Vi后面. 所以假如图里面有圈就不可能完成排序的. 第一种方法 一种简单的办法就是在排序算法中,先找到任意一个没有入边的顶点,然后显示该顶点,并把它和它的边一起从图里删掉.依次类推到最后. 入度(indegree): 顶点v的入度为,所有指向顶点v的变数(u, v). 出度(outdegree): 顶点v的出度为,顶点v所发出的边数(v, u). 下面写下这种方法的伪代码,因为这个的时间