拓撲排序是通過對有向無環圖進行深度優先搜索實現的,對於一個有向無環圖G來說,其拓撲排序是G中所有節點的一種線性排序,有很多生活活動都可以使用有向無環圖來指明事件的優先順序,比如下圖所示的早晨起牀過程:
上圖爲某人的早晨起牀涉及的一系列活動,圖中標註數字爲該圖可能存在的一種的一種深度優先搜索方案,有些事件之間存在必然的先後順序,比如打領帶之前比如穿襯衣,繫腰帶之前必須穿褲子等等,有些事件之間沒有必然的先後順序,比如穿襪子跟穿襯衣沒有必然的先後順序,所以該有向圖深度優先遍歷會生成一個森林。拓撲排序是在深度優先搜索過程中產生的,我們按照節點的截止時間倒敘排序形成的一個鏈表就是對應的拓撲排序,這裏僅將與深度排序不同的不同列舉出來,其他的可以參考筆者的另一篇文章:https://blog.csdn.net/john1337/article/details/104581678
//拓撲排序
@Test
public void topologicalSort(){
Graph g= new Graph(7);
Vertex v1 = new Vertex(1);
Vertex v2 = new Vertex(2);
Vertex v3 = new Vertex(3);
Vertex v4 = new Vertex(4);
Vertex v5 = new Vertex(5);
Vertex v6 = new Vertex(6);
Vertex v7 = new Vertex(7);
//初始化圖的頂點數組
g.addVertex(v1);
g.addVertex(v2);
g.addVertex(v3);
g.addVertex(v4);
g.addVertex(v5);
g.addVertex(v6);
g.addVertex(v7);
//初始化鄰接矩陣
v1.addVertex(v2);
v1.addVertex(v4);
//
v2.addVertex(v4);
v2.addVertex(v7);
//
v3.addVertex(v1);
v3.addVertex(v5);
//
v4.addVertex(v5);
v4.addVertex(v6);
//
v5.addVertex(v6);
//
v7.addVertex(v6);
//
System.out.println("以v3爲起始點遍歷");
init(g);
for(Vertex v:g.getVertexes()){
if(v.getColor() == VertexColor.WHITE){
dfsVisit(g,v);
}
}
//輸出拓撲排序
println("輸出拓撲排序");
for(Vertex v:toplogicalTree){
System.out.println(v.toString());
}
}
private void init(Graph g){
for(Vertex v:g.getVertexes()){
v.setColor(VertexColor.WHITE);
v.pre = null;
v.start =-1;
v.end =0;
}
//重置time
time = 0;
}
private void dfsVisit(Graph g,Vertex v){
time = time +1;
v.start = time;
v.setColor(VertexColor.GRAY);
for(Vertex c:v.getAdjList()){
if(c.getColor() == VertexColor.WHITE){
c.pre = v;
dfsVisit(g,c);
}
}
//遍歷完子節點
v.setColor(VertexColor.BLACK);
time = time +1;
v.end = time;
//下面的操作爲隊列操作,所以截止時間最大的將在隊列的最靠前位置
toplogicalTree.addFirst(v);
}
}
PS:
1、上面代碼中涉及到的所有類可以在https://blog.csdn.net/john1337/article/details/104581678博文中找到
2、拓撲排序算法的時間複雜度爲O(V+E),V爲該有向無環圖邊數,E爲該圖頂點數