相關(guān)概念
AOV網(wǎng):在一個(gè)表示工程的有向圖中,用頂點(diǎn)表示活動(dòng),用弧表示活動(dòng)之間的優(yōu)先關(guān)系,這樣的有向圖為頂點(diǎn)表示活動(dòng)的網(wǎng),稱為AOV網(wǎng)(Activity On Vertex)。
AVO網(wǎng)不存在環(huán)路
拓?fù)湫蛄校涸O(shè)G=(V,E)是一個(gè)具有n個(gè)頂點(diǎn)的有向圖,V中頂點(diǎn)序列V1,V2,......,Vn,滿足若從頂點(diǎn)Vi到Vj有一條路徑,則在頂點(diǎn)序列中頂點(diǎn)Vi必在頂點(diǎn)Vj之前,則這樣的頂點(diǎn)序列稱為一個(gè)拓?fù)湫蛄小?br> 拓?fù)湫蛄胁⒉晃ㄒ?/strong>
拓?fù)渑判蚓褪菢?gòu)造拓?fù)湫蛄械倪^程,當(dāng)AOV網(wǎng)中不存在環(huán)路時(shí),全部頂點(diǎn)都會(huì)被輸出。
拓?fù)渑判蛩惴?/h1>
思想:從AOV網(wǎng)中選擇一個(gè)入度為0的頂點(diǎn)輸出,然后刪除此頂點(diǎn),并刪除一次頂點(diǎn)為尾的弧,繼續(xù)重復(fù)該步驟,直至輸出全部頂點(diǎn)或者AOV網(wǎng)中不存在入度為0的頂點(diǎn)為止。
由于拓?fù)渑判蛐枰獎(jiǎng)h除頂點(diǎn),所以使用鄰接表的方式存儲(chǔ)圖會(huì)較為方便
鄰接表結(jié)構(gòu)
鄰接表的結(jié)構(gòu)不局限于此,可以根據(jù)實(shí)際情況添加字段,如在拓?fù)渑判蛑锌梢栽陧旤c(diǎn)表中增加入度字段,用于統(tǒng)計(jì)每個(gè)頂點(diǎn)的入度情況。在帶權(quán)圖中可以在邊表中添加weight字段,用于表示每條邊的權(quán)值。
測試圖:
對應(yīng)的鄰接表結(jié)構(gòu):
源代碼
頂點(diǎn)表類
/**
* 頂點(diǎn)表結(jié)點(diǎn)類
*
* @author Shaw
*
*/
class VertexNode {
// 頂點(diǎn)入度
private int in;
// 頂點(diǎn)域
private String data;
// 指向邊表
private EdgeNode firstEdge;
public VertexNode(int in, String data, EdgeNode firstEdge) {
super();
this.in = in;
this.data = data;
this.firstEdge = firstEdge;
}
public int getIn() {
return in;
}
public void setIn(int in) {
this.in = in;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
public EdgeNode getFirstEdge() {
return firstEdge;
}
public void setFirstEdge(EdgeNode firstEdge) {
this.firstEdge = firstEdge;
}
}
邊集表類:
/**
* 拓?fù)渑判? *
* @author Shaw
*
*/
public class Topological {
private List<VertexNode> verList;
//建圖
public void buildAovGraph() {
VertexNode v0 = new VertexNode(0, "v0", null);
EdgeNode v0e1 = new EdgeNode(11, 0, null);
EdgeNode v0e2 = new EdgeNode(5, 0, null);
EdgeNode v0e3 = new EdgeNode(4, 0, null);
v0.setFirstEdge(v0e1);
v0e1.setNext(v0e2);
v0e2.setNext(v0e3);
VertexNode v1 = new VertexNode(0, "v1", null);
EdgeNode v1e1 = new EdgeNode(8, 0, null);
EdgeNode v1e2 = new EdgeNode(4, 0, null);
EdgeNode v1e3 = new EdgeNode(2, 0, null);
v1.setFirstEdge(v1e1);
v1e1.setNext(v1e2);
v1e2.setNext(v1e3);
VertexNode v2 = new VertexNode(0, "v2", null);
EdgeNode v2e1 = new EdgeNode(9, 0, null);
EdgeNode v2e2 = new EdgeNode(6, 0, null);
EdgeNode v2e3 = new EdgeNode(5, 0, null);
v2.setFirstEdge(v2e1);
v2e1.setNext(v2e2);
v2e2.setNext(v2e3);
VertexNode v3 = new VertexNode(0, "v3", null);
EdgeNode v3e1 = new EdgeNode(13, 0, null);
EdgeNode v3e2 = new EdgeNode(2, 0, null);
v3.setFirstEdge(v3e1);
v3e1.setNext(v3e2);
VertexNode v4 = new VertexNode(0, "v4", null);
EdgeNode v4e1 = new EdgeNode(7, 0, null);
v4.setFirstEdge(v4e1);
VertexNode v5 = new VertexNode(0, "v5", null);
EdgeNode v5e1 = new EdgeNode(12, 0, null);
EdgeNode v5e2 = new EdgeNode(8, 0, null);
v5.setFirstEdge(v5e1);
v5e1.setNext(v5e2);
VertexNode v6 = new VertexNode(0, "v6", null);
EdgeNode v6e1 = new EdgeNode(5, 0, null);
v6.setFirstEdge(v6e1);
VertexNode v7 = new VertexNode(0, "v7", null);
VertexNode v8 = new VertexNode(0, "v8", null);
EdgeNode v8e1 = new EdgeNode(7, 0, null);
v8.setFirstEdge(v8e1);
VertexNode v9 = new VertexNode(0, "v9", null);
EdgeNode v9e1 = new EdgeNode(11, 0, null);
EdgeNode v9e2 = new EdgeNode(10, 0, null);
v9.setFirstEdge(v9e1);
v9e1.setNext(v9e2);
VertexNode v10 = new VertexNode(0, "v10", null);
EdgeNode v10e1 = new EdgeNode(13, 0, null);
v10.setFirstEdge(v10e1);
VertexNode v11 = new VertexNode(0, "v11", null);
VertexNode v12 = new VertexNode(0, "v12", null);
EdgeNode v12e1 = new EdgeNode(9, 0, null);
v12.setFirstEdge(v12e1);
VertexNode v13 = new VertexNode(0, "v13", null);
verList = new ArrayList<>();
verList.add(v0);
verList.add(v1);
verList.add(v2);
verList.add(v3);
verList.add(v4);
verList.add(v5);
verList.add(v6);
verList.add(v7);
verList.add(v8);
verList.add(v9);
verList.add(v10);
verList.add(v11);
verList.add(v12);
verList.add(v13);
}
public void topological_sort() {
Stack<Integer> stack = new Stack<>();
int count = 0;
// 初始化所有頂點(diǎn)表結(jié)點(diǎn)的入度值
for (int i = 0; i < verList.size(); i++) {
EdgeNode edgeNode = verList.get(i).getFirstEdge();
while (edgeNode != null) {
//邊集表中出現(xiàn)的下標(biāo)(adjvex)所對應(yīng)的頂點(diǎn)入度加1
VertexNode vertexNode = verList.get(edgeNode.getAdjvex());
vertexNode.setIn(vertexNode.getIn() + 1);
edgeNode = edgeNode.getNext();
}
}
// 將所有入度為0的頂點(diǎn)入棧
for (int i = 0; i < verList.size(); i++) {
if (verList.get(i).getIn() == 0) {
stack.push(i);
}
}
while (!stack.isEmpty()) {
// 從棧中彈出一個(gè)入度為0的頂點(diǎn)
int vertex = stack.pop();
System.out.print(verList.get(vertex).getData() + " -> ");
count++;
// 獲取彈出的頂點(diǎn)指向的第一個(gè)邊結(jié)點(diǎn)
EdgeNode edgeNode = verList.get(vertex).getFirstEdge();
while (edgeNode != null) {
// 獲取邊表結(jié)點(diǎn)的Adjvex值,該值存儲(chǔ)對應(yīng)頂點(diǎn)表結(jié)點(diǎn)的下標(biāo)值
int adjvex = edgeNode.getAdjvex();
// 獲取邊表結(jié)點(diǎn)指向的頂點(diǎn)表結(jié)點(diǎn)
VertexNode vertexNode = verList.get(adjvex);
// 刪除邊結(jié)點(diǎn),也就是將對應(yīng)的頂點(diǎn)表結(jié)點(diǎn)的入度減1
vertexNode.setIn(vertexNode.getIn() - 1);
// 如果該頂點(diǎn)表結(jié)點(diǎn)入度為0時(shí)壓棧
if (vertexNode.getIn() == 0) {
stack.push(adjvex);
}
// 獲取下一個(gè)邊表結(jié)點(diǎn)的值
edgeNode = edgeNode.getNext();
}
}
}
}
測試程序:
public class TopologicalMain {
public static void main(String[] args) {
// TODO Auto-generated method stub
Topological topological = new Topological();
topological.buildAovGraph();
topological.topological_sort();
}
}
測試結(jié)果: