TA的每日心情 | 开心 2021-3-12 23:18 |
---|
签到天数: 2 天 [LV.1]初来乍到
|
当每个任务有前后置关系时,需要找到一种满足前后置关系的路线,将任务完成。 如果将每个任务看成一个节点,任务之间的前后置关系表示为有向图时,这种路线顺序叫做为图进行拓扑排序。也叫关键路径分析。 比如有很多任务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=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);
-
- }
- /**
- * 图的拓扑排序
- * @param
- * @param graph
- * @return
- */
- 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); // c4->c5
- System.out.print("Visits: ");
- List< Vertex> vl=theGraph.topo();
- // List< Vertex> vl=theGraph.dfs(v1,false);
- System.out.println(vl);
- }
- }
-
复制代码
源码下载:http://file.javaxxz.com/2014/12/6/000719875.rar |
|