首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

深度优先搜索与有向无环图的拓扑排序(java兑现)

2012-12-27 
深度优先搜索与有向无环图的拓扑排序(java实现)当每个任务有前后置关系时,需要找到一种满足前后置关系的路

深度优先搜索与有向无环图的拓扑排序(java实现)
   当每个任务有前后置关系时,需要找到一种满足前后置关系的路线,将任务完成。

如果将每个任务看成一个节点,任务之间的前后置关系表示为有向图时,这种路线顺序叫做为图进行拓扑排序。也叫关键路径分析。

比如有很多任务T1,T2,....
    这些任务又是相互关联的,比如Tj完成前必须要求Ti已完成,这样T1,T2....序列关于这样的先决条件构成一个图,其中如果Ti必须要先于Tj完成,那么<Ti,Tj>就是该图中的一条路径,路径长度为1的就是一条边。拓扑排序就是把这些任务按照完成的先后顺序排列出来。显然,这样的顺序可能不是唯一的,比如Tk,Tl如果没有在一条路径上,那么他们之间的顺序是任意的。


    当从某顶点v出发的DFS搜索完成时,v的所有后继必定均已被访问过(想像它们均已被删除),此时的v相当于是无后继的顶点,因此在DFS算法返回之前输出顶点v即可得到 DAG的逆拓扑序列。
其中第一个输出的顶点必是无后继(出度为0)的顶点,它应是拓扑序列的最后一个顶点。若希望得到的不是逆拓扑序列,同样可增加T来保存输出的顶点。假设T是栈。
利用DFS求拓扑序列的抽象算法可描述为:
void DFSTopSort(G,i,T){//i是搜索的出发点,T是栈
  int j;
  visited[i]=TRUE; //访问i
  for(所有i的邻接点j)//即<i,j>∈E(G)
  if(!visited[j])
    DFSTopSort(G,j,T);
   Push(&T,i); //从i出发的搜索已完成,输出i
}

看看下图的一个拓扑序列:

[c1, c4, c0, c2, c3, c5, c6, c7, c8]



public enum VertexState {UNVISITED,VISITED,PASSED;//未访问,已访问,已经过}import java.util.Set;import java.util.List;import java.util.HashSet;import java.util.ArrayList;import java.util.Collections;//顶点类class Vertex   {    private String label;            private VertexState state;//顶点状态   public Vertex(String lab)         {      label = lab;      state = VertexState.UNVISITED;      }    public VertexState getState(){         return state;   }   public void setState(VertexState state){         this.state=state;   }   public String toString(){       return label;   }      } //有向图的邻接矩阵实现class Graph   {   private final int MAX_VERTS = 30;   private Vertex vertexList[]; // 存放顶点的数组   private int adjMat[][];      // 邻接矩阵   private int nVerts;          // 当前的顶点数    public Graph()                   {      vertexList = new Vertex[MAX_VERTS];                                               adjMat = new int[MAX_VERTS][MAX_VERTS];      nVerts = 0;      for(int y=0; y<MAX_VERTS; y++)               for(int x=0; x<MAX_VERTS; x++)               adjMat[x][y] = 0;            }      public  void addVertex(Vertex v)//在图中添加一个顶点      {      vertexList[nVerts++] = v;      }  //在图中增加一条边,从start到end   public void addEdge(int start, int end)      {      adjMat[start][end] = 1;         }       /** * 返回v顶点所关联的邻结点 * @param v * @return */   private Set<Vertex> getNeighbors(Vertex v){               Set<Vertex> vSet = new HashSet<Vertex>();       int index=getIndex(v);               if(index==-1) return null;               for(int i=0;i<nVerts;i++)                  if(adjMat[index][i]==1)                      vSet.add(vertexList[i]);            return vSet;}              //返回顶点在vertexList数组中的索引     private int getIndex(Vertex v){          for(int i=0;i<nVerts;i++)            if(vertexList[i]==v)                return i;           return -1;        }      /** * 全部节点设为未访问 */    private void allUnVisted(){Vertex v=null;int len = nVerts;     for(int i = 0; i < len ; i++){v = vertexList[i];if(v.getState() != VertexState.UNVISITED){v.setState(VertexState.UNVISITED);}      }    }    private boolean containsVertex(Vertex v){         int index=getIndex(v);         if(index!=-1) return true;         else return false;               }    private VertexState getState(Vertex v){return v.getState();}    private VertexState setState(Vertex v, VertexState state) {VertexState preState = v.getState();v.setState(state);return preState;}   /** * 深度优先遍历一个顶点 * @param  * @param graph * @param v * @param checkCycle * @return */    public List<Vertex> dfs(Vertex v,boolean checkCycle){allUnVisted();List<Vertex> vList = new ArrayList<Vertex>();dfsHandler(v,checkCycle,vList);return vList;}        private void dfsHandler(Vertex v,boolean checkCycle,List<Vertex> vList){          Set<Vertex> neighbors = null;if(!containsVertex(v)){ throw new IllegalStateException("不存在该顶点");}setState(v, VertexState.PASSED);neighbors = getNeighbors(v);VertexState state = null;for(Vertex neighbor : neighbors){   state = getState(neighbor);    if(state == VertexState.UNVISITED){//未遍历,                             //  System.out.println(neighbor+",");       dfsHandler(neighbor, checkCycle, vList);}else if(state == VertexState.PASSED && checkCycle){//                             throw new IllegalStateException("存在一个环");}}setState(v, VertexState.VISITED);//访问结束设为已访问vList.add(v);               // System.out.println("++"+v);               }         /** * 图的拓扑排序 */public List<Vertex> topo(){  List<Vertex> vList = new ArrayList<Vertex>();  allUnVisted();  for(int i=0;i<nVerts;i++){    if(getState(vertexList[i]) == VertexState.UNVISITED){try{  dfsHandler(vertexList[i], true, vList);}catch (IllegalStateException e) {  throw new IllegalStateException("图有一个环");}     }  }Collections.reverse(vList);return vList;    }}public class DFSApp   {   public static void main(String[] args)      {      Graph theGraph = new Graph();      Vertex v1=new Vertex("c0");      Vertex v2=new Vertex("c1");      Vertex v3=new Vertex("c2");      Vertex v4=new Vertex("c3");      Vertex v5=new Vertex("c4");      Vertex v6=new Vertex("c5");      Vertex v7=new Vertex("c6");      Vertex v8=new Vertex("c7");      Vertex v9=new Vertex("c8");           theGraph.addVertex(v1);    // 0        theGraph.addVertex(v2);    // 1      theGraph.addVertex(v3);    // 2      theGraph.addVertex(v4);    // 3      theGraph.addVertex(v5);    // 4      theGraph.addVertex(v6);    // 5        theGraph.addVertex(v7);    // 6      theGraph.addVertex(v8);    // 7      theGraph.addVertex(v9);    // 8      theGraph.addEdge(0, 6);     // c0->c6      theGraph.addEdge(0, 2);     // c0->c2      theGraph.addEdge(3, 5);     // c3->c5      theGraph.addEdge(3, 8);     // c3->c8      theGraph.addEdge(1, 2);     // c1->c2      theGraph.addEdge(1, 4);     // c1->c4      theGraph.addEdge(2, 3);     // c2->c3      theGraph.addEdge(6, 7);     // c6->c7      theGraph.addEdge(7, 8);     // c7->c8      theGraph.addEdge(4, 3);     // c4->c3      theGraph.addEdge(4, 5);     // c4->c5      //theGraph.addEdge(3, 1);     // c3->c1      System.out.print("Visits: ");      List<Vertex> vl=theGraph.topo();           // List<Vertex> vl=theGraph.dfs(v1,false);                  System.out.println(vl);      }     }


下载源文件:

热点排行