数据结构关键路径_数据结构与算法之关键路径_一点课堂(多岸学院)
關鍵路徑
梳理活動的順序僅僅是拓撲排序可以完成的功能之一,更有價值的是估量完成整個事件的最短時間。比如生產一輛汽車,雖然安排員工、準備原始材料是先行條件,但是組裝各種零部件是可以同時進行的,例如制造輪子和發動機、外殼等是可以同時進行的,這樣可以大大減少生產時間。這種場景我們稱為AOE網。
在一個表示工程的帶權有向圖中,用頂點表示事件,用有向邊表示活動,用邊上的權值表示活動的持續時間,這種有向圖的邊表示活動的網,稱之為AOE網(Activity On Edge Network)。
我們的目標就是在這樣的AOE網中,確定它的最短完成時間,而具備最短時間的路徑就是關鍵路徑。
把路徑上各個活動所持續的時間之和稱為路徑長度,從起點到終點具有最大長度的路徑叫關鍵路徑,在關鍵路徑上的活動叫關鍵活動。
那么我們怎么確定一個活動是不是關鍵活動呢?以做飯為例,我們可以同時燒水、炒菜和熬粥,其中燒水只需要3分鐘,炒菜需要10分鐘,熬粥需要20分鐘。那么很顯然至少需要20分鐘才能完成全部工作,也就是說在這20分鐘時間里,熬粥必須從一開始就進行,而燒水則可以從開始進行,也可以等17分鐘后再進行,炒菜也可以從開始進行,或者最晚等10分鐘后進行。這里沒有空閑時間的活動就是關鍵活動。
例如下圖就是一個AOE網,其中權值表示活動需要的時間:
以從v0->v3為例,假設權值表示的時間單位為分鐘,可選的路徑有v0->v1->v3,需要8分鐘,或者v0->v2->v3,需要12分鐘。要盡快到達v3,則v2必須一開始立刻啟動,而v1可以在最開始,或者等待4分鐘之后再啟動,所以v0->v2->v3是關鍵路徑。按照此方式,可以得到此AOE網的關鍵路徑如下:
那么接下來,我們只需要確認每個頂點的最早開始時間和最晚開始時間,判斷它們的時間差,如果沒有時間差就是關鍵路徑。
代碼實現
首先,我們需要對AOE網進行拓撲排序,在排序的同時還可以得到每個頂點事件的最早發生時間,代碼如下所示:
public boolean topoSort(ATGraph atGraph,int[] earlestTimeVertex,Stack> stack2) { int count = 0; Queue> queue = new LinkedList<>(); for (int i = 0; i < atGraph.getLen(); i++) { if (atGraph.getVertex(i).getIn() == 0) { queue.offer(atGraph.getVertex(i)); } } while (!queue.isEmpty()) { ATVertex vertex = queue.poll(); System.out.print(vertex.getData() + "->"); //將排序的數據push到stack2中 stack2.push(vertex); count++; //獲取第一條邊 ATEdge next = vertex.getNext(); while (next != null) { //獲取 ATVertex nextVertex = next.getVertex(); nextVertex.setIn(nextVertex.getIn() - 1); if (nextVertex.getIn() == 0) { queue.offer(nextVertex); } // 計算每個頂點可以執行的最早時間 // 獲取弧尾頂點下標 int topIndex = atGraph.getVertexIndex(vertex); // 獲取弧頭頂點下標 int index = atGraph.getVertexIndex(nextVertex); // 更新當前頂點可以發生的最早時間 if (earlestTimeVertex[topIndex] + next.getWeight() > earlestTimeVertex[index]) { earlestTimeVertex[index] = earlestTimeVertex[topIndex] + next.getWeight(); } next = next.getNext(); } } return count >= atGraph.getLen();}現在我們得到了最早發生時間,并且將全部頂點按照訪問的先后順序壓進了一個棧中,這是為了方便進行計算最晚發生時間。從前向后計算最晚發生時間是復雜的,但是反過來卻很簡單,對于最后一個頂點,它的最晚發生時間和最早發生時間一定一致,而它前面的頂點,就必須在此時間點之前完成。參考代碼如下:
for (int i = 0; i < atGraph.getLen(); i++) { // 先將最晚發生時間都設置為最長時間 latestTimeVertex[i] = earlestTimeVertex[atGraph.getLen()-1];}// 從后向前,更新每個頂點的最晚發生時間while (!stack2.isEmpty()){ ATVertex vertex = stack2.pop(); ATEdge next = vertex.getNext(); while (next!=null){ ATVertex nextVertex = next.getVertex(); int nextIndex = atGraph.getVertexIndex(nextVertex); int index = atGraph.getVertexIndex(vertex); if (latestTimeVertex[nextIndex]-next.getWeight()最后,只要按照順序比對這兩個時間是否相等,就可以得到完整的關鍵路徑了,完整代碼如下:
public void criticalPath(ATGraph atGraph){ Stack> stack2 = new Stack<>(); int[] earlestTimeVertex = new int[atGraph.getLen()]; int[] latestTimeVertex = new int[atGraph.getLen()]; topoSort(atGraph,earlestTimeVertex,stack2); for (int i = 0; i < atGraph.getLen(); i++) { // 先將最晚發生時間都設置為最長時間 latestTimeVertex[i] = earlestTimeVertex[atGraph.getLen()-1]; } // 從后向前,更新每個頂點的最晚發生時間 while (!stack2.isEmpty()){ ATVertex vertex = stack2.pop(); ATEdge next = vertex.getNext(); while (next!=null){ ATVertex nextVertex = next.getVertex(); int nextIndex = atGraph.getVertexIndex(nextVertex); int index = atGraph.getVertexIndex(vertex); if (latestTimeVertex[nextIndex]-next.getWeight() vertex = atGraph.getVertex(i); ATEdge next = vertex.getNext(); while (next!=null){ ATVertex nextVertex = next.getVertex(); int nextIndex = atGraph.getVertexIndex(nextVertex); lte = latestTimeVertex[nextIndex]-next.getWeight(); ete = earlestTimeVertex[i]; if (ete==lte){ System.out.println("路徑:"+atGraph.getVertex(i).getData()+"->"+atGraph.getVertex(nextIndex).getData()+總結
以上是生活随笔為你收集整理的数据结构关键路径_数据结构与算法之关键路径_一点课堂(多岸学院)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 51单片机智能小车循迹完整程序_电气与信
- 下一篇: node中间件mysql_nodejs