图的遍历算法分析及应用(3)--拓扑排序

    对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若<u,v> ∈E(G),则u在线性序列中出现在v之前。如下图

《图的遍历算法分析及应用(3)--拓扑排序》

    拓扑排序序列还可以为:C1,C3,C2,C4,C6,C5,C7当然还有别的可能。对于这些基础概念在此就不在强调,相信学过学过数据结构的同学,都知道它的概念,在此我们只要来看看拓扑排序的算法实现,以及各种算法的分析。

   

 实现1:

bool TopologicalSortingVer1(int G[][Max],int Result[])
{
      // 时间复杂度o(n~3)
      int i,j,k;
      bool Visit[Max];
      for(i=0;i<Max;i++)Visit[i]=false;

      for(k=0;k<Max;k++){
            for(i=0;i<Max;i++){
                 if(Visit[i])continue;
                 for(j=0;j<Max;j++){
                       if(G[j][i]==1)break;
                 }
                if(j<Max)continue;         
                Visit[i]=true;
                for(j=0;j<Max;j++)G[i][j]=2;
                Result[k]=i;
                break;
          }
      if(i>=Max) return false;
    }
    return true;
}

    这是一种很直接的想法,最外层的K循环,表示已经排序的个数,第二层的循环i表示从n个顶点中寻找一个还没有被排序的顶点(每次只找一个,当然可以改进,找多个),一旦找到,再判断这个顶点的入度是否为零,这就是第三层循环j。一旦不能找到这样入度为零的顶点了,排序结束,即存在有向圈。 这种算法的时间复杂度o(n~2)<T<o(n~3).

 

 

 实现2:

void GetdInDegree(int G[][Max],int Degree[])
{
     for(int i=0;i<Max;i++){
        Degree[i]=0;
        for(int j=0;j<Max;j++)
             Degree[i]+=G[j][i];
     }
}

bool TopologicalSortingVer2(int G[][Max],int Result[])
{
      using std::stack;
      // 时间复杂度
      int i,j;
      int Degree[Max];
      stack<int> Mystack;

      GetdInDegree(G,Degree);//o(n~2)或o(e);
      for(i=0;i<Max;i++)//o(n);
           if(Degree[i]==0)Mystack.push(i);
   
     int Count=0;
     while(!Mystack.empty()){
          Result[Count]=Mystack.top();
          Mystack.pop();
          for(j=0;j<Max;j++)
               if(G[Result[Count]][j]==1){
                     Degree[j]–;
                     if(Degree[j]==0)Mystack.push(j);
               }
          Count++;
      }

     //while循环的时间复杂度分析类型与深度优先搜索,每个元素仅仅进出栈一次,在每一次出栈后寻找他的邻接点(邻接表储存矩阵时o(n)邻接表储存时o(e_1),)
     //所以while循环时间复杂度为o(n~2)或o(e)
     if(Count<Max)return false;
     return true;  
     //所以总的时间度为o(n~2)或o(n+e);
}

   这种版本i就是数据结构(严蔚敏版本)书中介绍的,在此就不多说了。

   

 

实现3:

int Index=Max-1;
void DFS_TopologicalSorting(int G[][Max],int BeginVer,int Result[])
{
      Visited[BeginVer]=true;
      for(int i=0;i<Max;i++)
          if(IsEdgeFuncion(G,BeginVer,i)&&!Visited[i]){
                 DFS_TopologicalSorting(G,i,Result);
          }
      Result[Index–]=BeginVer;
}

bool TopologicalSortingVer3(int G[][Max],int Result[],bool(*IsEdgeFun)(int G[][Max],int, int))
{
       int i,BeginVer=0;
       for(i=0;i<Max;i++)Visited[i]=false;
       IsEdgeFuncion=IsEdgeFun;

       DFS_TopologicalSorting(G,BeginVer,Result);
       if(Index>=0)return false;
       else return true;
       //时间复杂度类似于深度优先遍历为:o(n~2)或o(n+e)
}

数据结构书中提到过,可以利用深度优先来实现拓扑排序,但没有给出实现,在此我们利用深度优先的递归版本来实现这个算法。

    原文作者:数据结构之图
    原文地址: https://blog.csdn.net/z568954956/article/details/6715115
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞