Java實現AOV圖的拓撲排序

c6g3 9年前發布 | 29K 次閱讀 Java 算法

拓撲排序作為圖的應用,了解拓撲排序必須首先了解AOV圖。

AOV網表示一個有向圖中頂點,用弧表示頂點之間的優先關系。如下圖所示,在AOV網中,若從頂點vi到頂點vj之間存在一條有向路徑,則稱頂點vi為頂點vj的前驅,頂點vj為頂點vi的后繼。注意,AOV圖不能有回路,否則會將序列陷入死循環,稱為死鎖。

進行拓撲排序,一般步驟如下:

<1>在AOV網中選擇一個入度為0的頂點

<2>在AOV網中刪除此頂點及其相連的有向邊

<3>重復步驟<1>和<2>,直到AOV網中沒有入度為0的頂點為止

由于拓撲排序具有不確定性,因此經過排序的序列應人而異,不過大多序列的邏輯關系能夠走通。


程序如下:

package 拓撲排序;
/*
 * 在AOV網中尋找拓撲排序序列的步驟如下:
 * <1>在AOV網中選擇一個入度為0的頂點
 * <2>從AOV往中刪除此頂點以及與其相連的有向邊
 * <3>重復步驟<1>和<2>。直到AOV網中沒有入度為0的頂點
 */
public class TopoSort {
 /**
  * @author 劉雁冰
  * @date 2015-02-14 20:22
  */
 
 /*
  * Max:定義頂點的最大容量為100
  * ver:使用內部Vertexs類創建一個數組ver,存儲頂點的關鍵字
  * map:AOV網的鄰接矩陣表
  * n:頂點的數量
  * topoSort:存儲最終得到的序列
  */
 static int Max=100;
 static Vertexs ver[];
 static int map[][];
 static int n;
 static char topoSort[];
 
 public static void main(String[] args) {
  // TODO Auto-generated method stub
  ver=new Vertexs[Max];
  map=new int[Max][Max];
  n=0;
  topoSort=new char[Max];
  //初始化鄰接矩陣
  for(int i=0;i<Max;i++){
   for(int j=0;j<Max;j++){
    map[i][j]=0;
   }
  }
  TopoSort ts=new TopoSort();
  //讀入AOV網頂點的關鍵字
  ts.addVertex('A');
  ts.addVertex('B');
  ts.addVertex('C');
  ts.addVertex('D');
  ts.addVertex('E');
  ts.addVertex('F');
  ts.addVertex('G');
  ts.addVertex('H');
  ts.addVertex('I');
  ts.addVertex('J');
  ts.addVertex('K');
  ts.addVertex('L');
  
  //讀入AOV網邊的連接信息,由于是有向圖,只需讀入一次
  ts.addEdge(0, 1);
  ts.addEdge(0, 3);
  ts.addEdge(0, 10);
  ts.addEdge(1, 10);
  ts.addEdge(2, 3);
  ts.addEdge(2, 4);
  ts.addEdge(2, 5);
  ts.addEdge(3, 7);
  ts.addEdge(5, 7);
  ts.addEdge(5, 6);
  ts.addEdge(5, 8);
  ts.addEdge(6, 8);
  ts.addEdge(6, 9);
  ts.addEdge(10, 11);
  ts.addEdge(11, 9);
  ts.addEdge(11, 6);
  
  ts.topoSort();
 }
 
 //構造頂點關鍵字數組
 public void addVertex(char v){
  ver[n++]=new Vertexs(v);
 }
 
 //構造邊的鄰接矩陣
 public void addEdge(int start,int end){
  map[start][end]=1;
 }
 
 public void topoSort(){
  //num:頂點數量n要進行遞減,因此起始存入num,作為輸出序列遍歷使用
  //isEdge:判定該邊是否相連
  int num=n;
  boolean isEdge;
  
  while(n>0){
   //選取一個入度為0的頂點
   int currVer=0;
   //遍歷鄰接矩陣
   for(int row=0;row<n;row++){
    isEdge=false;
    for(int col=0;col<n;col++){
     if(map[row][col]>0)
      isEdge=true;
    }
    //抽取鄰接邊表中沒有出度的頂點(將鄰接表行數賦值給當前頂點)
    if(!isEdge)
     currVer=row;
   }
   //將沒有出度的頂點存入序列結果最后的位置
   topoSort[n-1]=ver[currVer].value;
   
  /*
   *  刪除頂點操作
   * 當前頂點不為最后頂點時進行
   */
   if(currVer!=n-1){
    //頂點關鍵字數組往后移動一位
    for(int i=currVer;i<n;i++)
     ver[i]=ver[i+1];
    
    /*
     * 移動鄰接表行列,覆蓋原值
     */
    //鄰接表行數往后移動一位(向右移動)
    for(int row=currVer;row<n-1;row++)
     for(int col=0;col<n;col++)
      map[row][col]=map[row+1][col];
    //鄰接表列數往后移動一位(向左移動)
    for(int col=currVer;col<n-1;col++)
     for(int row=0;row<n;row++)
      map[row][col]=map[row][col+1];
   }
   n--;   //下一個頂點
  }
  
  //輸出結果
  System.out.println("該圖的拓撲排序序列為:");
  for(int i=0;i<num;i++){
  }
 }
}
class Vertexs{
 public char value;
 public Vertexs(char v){
  value=v;
 }
}


測試結果如下:

 本文由用戶 c6g3 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!