TA的每日心情  | 开心 2021-3-12 23:18 | 
|---|
 
  签到天数: 2 天 [LV.1]初来乍到  
 | 
 
| 
 
 对一个有向无环图(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,C6,C7,C1,C4,C2,C3,C8,C5。 
    
   
     
     
      
     
 
      
     
   
   
  
 ⑤当有向图中存在有向环时,拓扑序列不存在 
  
 无后继的顶点优先拓扑排序方法 
  
 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中存在有向环,排序失败!"); 
 } 
  
 代码:- //有向无环图的拓扑排序:
 
 - //第一步:在图中找到一个没有后继的顶点;
 
 - //第二步:从图中删除这个顶点,在列表的前面插入顶点的标记
 
 - //第三步:重复第一和第二步,直到所有顶点都从图中删除。这时列表显示的顶点顺序就是拓扑排序的结果。
 
 - class Vertex {
 
 -    public char label;       
 
 -    public Vertex(char lab)  
 
 -       { label = lab; }
 
 -    }  
 
 - class Graph{
 
 -    private final int MAX_VERTS = 20;
 
 -    private Vertex vertexList[]; //顶点列表
 
 -    private int adjMat[][];     //邻接矩阵 
 
 -    private int nVerts;          // 当前的顶点数
 
 -    private char sortedArray[];// 已经排序的顶点
 
 -  Graph() {
 
 -       vertexList = new Vertex[MAX_VERTS];
 
 -                                         
 
 -       adjMat = new int[MAX_VERTS][MAX_VERTS];
 
 -       nVerts = 0;
 
 -       for(int j=0; j< MAX_VERTS; j++)     
 
 -          for(int k=0; k< MAX_VERTS; k++)
 
 -             adjMat[j][k] = 0;
 
 -       sortedArray = new char[MAX_VERTS];  
 
 -       }  
 
 -    public void addVertex(char lab)//在图中增加一个顶点
 
 -       {
 
 -       vertexList[nVerts++] = new Vertex(lab);
 
 -       }
 
 -    public void addEdge(int start, int end)//在图中增加一条边
 
 -       {
 
 -       adjMat[start][end] = 1;
 
 -       }
 
 -    public void displayVertex(int v)
 
 -       {
 
 -       System.out.print(vertexList[v].label);
 
 -       }
 
 -    public void topo(){
 
 -       int orig_nVerts = nVerts;  
 
 -       while(nVerts > 0){
 
 -         
 
 -          int currentVertex = noSuccessors();//找一个没有后继的顶点(出度为0)
 
 -           
 
 -          if(currentVertex == -1){      // 没有找到,一定是一个环
 
 -             System.out.println("ERROR: Graph has cycles");
 
 -             return;
 
 -          }
 
 -          // 找到了,插入
 
 -          sortedArray[nVerts-1] = vertexList[currentVertex].label;
 
 -          deleteVertex(currentVertex);  // 删除顶点
 
 -       }  
 
 -       // 显示拓扑排序的结果
 
 -       System.out.print("Topologically sorted order: ");
 
 -       for(int j=0; j< orig_nVerts; j++)
 
 -          System.out.print( sortedArray[j] );
 
 -       System.out.println("");
 
 -       }  
 
 -    public int noSuccessors(){ // 从邻接矩阵中找一个没有后继的顶点(出度为0的)                   
 
 -       boolean isEdge;  
 
 -       for(int row=0; row< nVerts; row++){
 
 -          isEdge = false;                 
 
 -          for(int col=0; col< nVerts; col++){
 
 -             if( adjMat[row][col] > 0 ){                        
 
 -                isEdge = true;
 
 -                break;                   
 
 -                }                     
 
 -          }                        
 
 -          if( !isEdge )    
 
 -             return row;   
 
 -       }
 
 -       return -1;      
 
 -    }  
 
 -    //删除一个顶点。顶点从vertexList[]数组删除,后面的顶点向前移动填补空位,同样的,顶点所在的行列
 
 -   //从邻接矩阵中删除,下面的行的右面的列移动来填补空位。
 
 -    public void deleteVertex(int delVert){
 
 -       if(delVert != nVerts-1) {// 如果不是最后一个顶点
 
 -          for(int j=delVert; j< nVerts-1; j++)
 
 -             vertexList[j] = vertexList[j+1];
 
 -          // 在邻接矩阵中删除一行
 
 -          for(int row=delVert; row< nVerts-1; row++)
 
 -             moveRowUp(row, nVerts);
 
 -          // 在邻接矩阵中删除一列
 
 -         for(int col=delVert; col< nVerts-1; col++)
 
 -             moveColLeft(col, nVerts-1);
 
 -       }
 
 -       nVerts--;                  
 
 -    } 
 
 -    private void moveRowUp(int row, int length){
 
 -       for(int col=0; col< length; col++)
 
 -          adjMat[row][col] = adjMat[row+1][col];
 
 -       }
 
 -    private void moveColLeft(int col, int length){
 
 -       for(int row=0; row< length; row++)
 
 -          adjMat[row][col] = adjMat[row][col+1];
 
 -       }
 
 -    }  
 
 - public class TopoApp {
 
 -    public static void main(String[] args){
 
 -       Graph theGraph = new Graph();
 
 -       theGraph.addVertex("0");    
 
 -       theGraph.addVertex("1");    
 
 -       theGraph.addVertex("2");    
 
 -       theGraph.addVertex("3");    
 
 -       theGraph.addVertex("4");    
 
 -       theGraph.addVertex("5");    
 
 -       theGraph.addVertex("6");   
 
 -       theGraph.addVertex("7");    
 
 -       theGraph.addVertex("8");    
 
 -       theGraph.addEdge(0, 6);    
 
 -       theGraph.addEdge(0, 2);    
 
 -       theGraph.addEdge(6, 7);     
 
 -       theGraph.addEdge(7, 8);     
 
 -       theGraph.addEdge(2, 3);     
 
 -       theGraph.addEdge(1, 2);     
 
 -       theGraph.addEdge(1, 4);    
 
 -       theGraph.addEdge(4, 5);  
 
 -       theGraph.addEdge(4, 3);   
 
 -       theGraph.addEdge(3, 5); 
 
 -       theGraph.addEdge(3, 8);                
 
 -     
 
 -       theGraph.topo();            // do the sort
 
 -       }  
 
 -    }  
 
 
  复制代码 运行结果: 
 C:        est>java TopoApp 
 Topologically sorted order: 067142385 
  
  
   
   
     
     
 
      
     
 
      
     
   
 
源码下载:http://file.javaxxz.com/2014/12/7/000708140.zip |   
 
 
 
 |