拓扑排序:
AOV网:为了反映出整个工程中活动之间的领先关系,可以用一个有向图表示工程,图中的顶点代表活动,图中的有向边代表活动间的领先关系,则该图称作顶点活动网(Activity On Vertex netowrk, AOV网)
拓扑排序定义:是指求AOV网中各顶点的拓扑序列的运算,一个拓扑序列是AOV网中各顶点的线性序列,该序列满足:若AOV网中有从顶点 i 到顶点 j 的一条路径,则在该线性序列(拓扑序列)中,顶点 i 必然在顶点 j 之前
进行拓扑排序的实际意义:若AOV网中所有顶点都在它的拓扑序列中,说明该网不存在有回路,整个工程可以顺利进行
拓扑排序步骤:
1.在图中选择一个入度为0的顶点并输出它
2.从图中删除这个顶点及其所有出边
重复1,2,直到不存在入度为0的顶点,若此时输出的顶点数小于原图中顶点数,说明图中存在回路,否则,顶点输出的序列就是其对应的拓扑序列
代码实现:
采用减治法,寻找图中入入度为0的顶点作为即将遍历的顶点,遍历完之后,将这个顶点删除
//参数为领接矩阵,G[i][j] = 1表示顶点i到顶点j有一条路径
public void topologicalSorting(int[][] G){
//首先获得每一个顶点的入度
int[] source = new int[G.length];
for(int i=0;i<G.length;i++){
int count = 0;
for(int j=0;j<G.length;j++){
//G[j][i]==1表示顶点i入度+1
if(G[j][i]==1){
count++;
}
}
source[i] = count;
}
//用来保存拓扑序列
ArrayList<Integer> topological = new ArrayList<>();
//用stack来保存入度为0的顶点
LinkedList<Integer> stack = new LinkedList<>();
for(int i=0;i<source.length;i++){
if(source[i]==0){
stack.addLast(i);
}
}
int cnt = 0;
while(true){
//当所有入度为0的顶点全部遍历完之后,但是循环没有自行跳出,说明原图中有环
if(stack.isEmpty()){
System.out.println("图中存在环");
break;
}
int i = stack.getFirst();
//当某个顶点的入度为0,遍历这个顶点
//拓扑序列中的顶点个数+1
cnt++;
topological.add(i);
//在stack中删除当前顶点
stack.removeFirst();
//删除当前顶点的出边
for(int j=0;j<G[0].length;j++){
//i为当前顶点,G[i][j]==1说明需要删除i到j这条边,即顶点j的入度-1,所以是source[j]--;
if(G[i][j]==1){
source[j]--;
if(source[j]==0){
//如果入度为0,将其添加到stack中
stack.addLast(j);
}
}
}
if(cnt==G.length){
break;
}
}
for(int n:topological){
System.out.println(n);
}
}
最后topological中存放的就是本次拓扑排列拓扑序列,注意,一个图中可能不止一中拓扑序列