拓扑排序(Topological Order)是指,将一个有向无环图(Directed Acyclic Graph简称DAG)进行排序进而得到一个有序的线性序列。
这样说,可能理解起来比较抽象。下面通过简单的例子进行说明!
例如,一个项目包括A、B、C、D四个子部分来完成,并且A依赖于B和D,C依赖于D。现在要制定一个计划,写出A、B、C、D的执行顺序。这时,就可以利用到拓扑排序,它就是用来确定事物发生的顺序的。
在拓扑排序中,如果存在一条从顶点A到顶点B的路径,那么在排序结果中B出现在A的后面。
拓扑排序步骤
- 构造拓扑排序的结果队列T(topological);
- 计算所有顶点的入度;
- 如果存在入度为零且没有排序过的顶点,则
3.1 将入度为0的顶点放入队列T,
3.2 去掉以这些顶点为起点的边,
3.3 标记这些顶点已经被排序过,
3.4 返回步骤2,重新计算剩余定点入度 - 若果未排序的顶点入度都不为零,说明剩余的顶点组成了环,返回-1
Java实现
邻接矩阵图数据结构实现
承接前文的MatrixDG数据结构:
public int topoSort(){ boolean[] visited=new boolean[size]; for(int i=0;i<size;i++){ visited[i]=false; } LinkedList<Integer> topo=new LinkedList<Integer>(); int result=topoSort(visited,topo); if(result==1){ for(int i=0;i<topo.size();i++){ System.out.println(vertexs[topo.get(i)]+" "); } } return result; } public int topoSort(boolean[] visited,LinkedList<Integer> topo){ int[] inDegree=new int[size]; for(int i=0;i<size;i++){ inDegree[i]=0; for(int j=0;j<size;j++){ if(matrix[j][i]!=0&&visited[j]==false){ inDegree[i]++; } } } boolean hasCircle=true; for(int i=0;i<size;i++){ if(inDegree[i]==0&&visited[i]==false){ hasCircle=false; topo.add(i); visited[i]=true; } } if(hasCircle){ System.out.println("Has Circle"); return -1; } if(size!=topo.size()){ return topoSort(visited,topo); }else{ return 1; } }
邻接表图数据结构实现
承接前文的ListDG数据结构:
public int topoSort(){ boolean[] visited=new boolean[size]; for(int i=0;i<size;i++){ visited[i]=false; } LinkedList<Vertex> topo=new LinkedList<Vertex>(); int result=topoSort(visited,topo); if(result==1){ for(int i=0;i<topo.size();i++){ System.out.println(topo.get(i).ch); } } return result; } private int topoSort(boolean[] visited,LinkedList<Vertex> topo){ int[] inDegree=new int[size]; for(int i=0;i<size;i++){ Vertex node=vertexLists[i]; while(node!=null){ if(visited[i]==false){ inDegree[getPosition(node.ch)]++; } node=node.next; } inDegree[i]--; } boolean hasCircle=true; for(int i=0;i<size;i++){ if(inDegree[i]==0&&visited[i]==false){ hasCircle=false; topo.add(vertexLists[i]); visited[i]=true; } } if(hasCircle){ System.out.println("Has Circle"); return -1; } if(size!=topo.size()){ return topoSort(visited,topo); }else{ return 1; } }