日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

拓扑排序--关键路径

發布時間:2025/6/15 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 拓扑排序--关键路径 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

拓撲排序和關鍵路徑是基于無環的有向圖。

主要用來表示工程進度中各個事件之間的關系。

?拓撲排序和關鍵路徑?使用鄰接表存儲數據,最小生成樹和最短路徑用?鄰接矩陣?存儲數據。

1、拓撲排序

AOV網:在一個表示工程的有向圖中,用固定點表示活動,用弧表示活動之間的優先級關系,這樣的有向圖為頂點表示活動的網,我們稱之為AOV網(Activity?On?Vertex?Network)

拓撲排序:是將一個AOV網的各個頂點按一定順序排列,要求滿足若存在<Vi,Vj>,則排序中的頂點Vi必在頂點Vj之前。對于同一幅圖,拓撲排序可有多個拓撲排序。

在顯示生活中,用到的拓撲排序的例子:

????????學校課程布置圖,要先修完一些基礎課,才可以繼續修專業課,以計算機軟件專業為例,在《程序設計基礎》和《離散數學》課程學完之前就不能開始學習《數據結構》,這些先決條件定義了課程之間的優先(領先)關系。

算法:

(1)從有向圖中選擇一個無前驅(入度為0)的頂點輸出。

(2)刪除此頂點,并刪除已此頂點為為尾的弧。

(3)重復(1),(2)步驟,知道輸出全部頂點或者AOV網中不存在入度為0的頂點。

具體實現代碼:

????用棧來保存入度為0的頂點,和更新后入度為0的頂點

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 #include <stdio.h> #define MAXVEX 100 typedef?struct?EdgeNode???/*邊表節點*/ { int?adjvex;???????/*鄰接點域,存儲該頂點對應的下表*/ int?weight;???????/*用于存儲權值,對于非網圖可以不需要*/ struct?EdgeNode *next;??/*鏈域,指向下一個鄰節點*/ }EdgeNode; typedef?struct?VertexNode???/*頂點表節點*/ { int?in;??????????/*頂點入度*/ int?data;???????/*頂點域,存儲頂點信心*/ EdgeNode *firstedge;?/*邊表頭指針*/ }VertexNode, Adjlist[MAXVEX]; typedef?struct { Adjlist adjList; int?numVertexes; int?numEdges;??/*圖中當前頂點數和邊數*/ }graphAdjList, *GraphAdjList; /*拓撲排序,若GL無回路,則輸出拓撲排序序列并返回OK,若有回路返回ERROR*/ int?TopoLogicalSort(GraphAdjList GL) { EdgeNode *e; int?i,k,gettop; int?top = 0;???/*用于棧指針下表*/ int?count = 0;?/*用于統計輸出頂點的個數*/ int?*stack;??/*建棧用于存儲入度為0的頂點*/ stack = (int*)malloc(GL->numVertexes *sizeof(int));??//動態分配內存,大小為n個頂點(最多有n個頂點入度為0,因為圖總共有n個頂點) for(i = 0; i<GL->numVertexes; i++) if(GL->adjList[i].in == 0)??/*將入度為0的頂點入棧*/ stack[++top] = i; while(top != 0) { gettop = stack[top--];??/*出棧*/ printf("%d -> ",GL->adjList[gettop].data);?/*打印此頂點*/ count++;?/*統計輸出頂點數*/ for(e=GL->adjList[gettop].firstedge; e!; e=e->next) {?/*對此頂點弧表遍歷*/ k = e->adjvex; if(--GL->adjList[k].in == 0)??//將k號頂點鄰接點的入度減1,且減1后,入度為0的頂點需要存到棧中 stack[++top] = k; } } if(count < GL->numVertexes)??/*如果count小于頂點數,說明存在環*/ return?-1; else return?0; }

?

分析整個算法,對一個具有n個頂點e條弧的AOV網來說,將入度為0的頂點入棧的時間復雜度為O(n),而之后的while循環中,每個頂點入一次棧,出一次棧,入度減1的操作執行了e次,所以整個算法時間復雜度為O(n+e)。

2、關鍵路徑

拓撲排序是解決一個工程能否順序進行的問題,但有時還需解決工程完成需要的最短時間。

AOE網:在一個表示工程帶權的有向圖中,用頂點表示事件,用有向邊表示活動,用邊上的權值表示活動的持續時間,這種用有向圖的邊表示活動的網,我們稱之為AOE網(Activity?On?Edge?Network)

用ve(i)表示事件(即頂點)i的最早開始時間,用vl(i)表示事件i的最開始時間,如果活動k由弧<m,n>表示,用dut(<m,n>)表示活動的持續時間,則有:

e(k)?=?ve(m)

l(k)?=?vl(n)?-?dut(<m,n>)

求解關鍵路徑的具體算法(假設圖中有n個頂點)

(1)?從開始頂點V0出發,假設ve(0)=0,然后按照拓撲有序求出其他各頂點i的最早開始時間ve(i),如果得到拓撲序列中頂點數目小于圖中的頂點數,則表示圖中存在回路,算法結束,否則繼續執行。

(2)從結束頂點Vn出發,假設vl(n-1)?=?ve(n-1);然后求出各頂點i的最晚發生時間。

(3)根據頂點的最早發生時間,和最晚發生時間,依次求出出每條弧的最早開始時間和最晚開始時間,如果兩只相等,則為關鍵活動。關鍵活動組成的路徑則為關鍵路徑。

具體實現代碼:

?

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 #include <stdio.h> #define MAXVEX 100 /*首先聲明幾個全局變量*/ int?*etv,*ltv;??/*時間的最早發生時間和最遲發生時間*/ int?*stack2;??/*用于存儲拓撲序列的棧*/ int?top2;????/*用于stack2的指針*/ typedef?struct?EdgeNode???/*邊表節點*/ { int?adjvex;???????/*鄰接點域,存儲該頂點對應的下表*/ int?weight;???????/*用于存儲權值,對于非網圖可以不需要*/ struct?EdgeNode *next;??/*鏈域,指向下一個鄰節點*/ }EdgeNode; typedef?struct?VertexNode???/*頂點表節點*/ { int?in;??????????/*頂點入度*/ int?data;???????/*頂點域,存儲頂點信心*/ EdgeNode *firstedge;?/*邊表頭指針*/ }VertexNode, Adjlist[MAXVEX]; typedef?struct { Adjlist adjList; int?numVertexes; int?numEdges;??/*圖中當前頂點數和邊數*/ }graphAdjList, *GraphAdjList; /*拓撲排序,若GL無回路,則輸出拓撲排序序列并返回OK,若有回路返回ERROR*/ int?TopoLogicalSort(GraphAdjList GL) { EdgeNode *e; int?i,k,gettop; int?top = 0;???/*用于棧指針下表*/ int?count = 0;?/*用于統計輸出頂點的個數*/ int?*stack;??/*建棧用于存儲入度為0的頂點*/ stack = (int*)malloc(GL->numVertexes *sizeof(int));??//動態分配內存,大小為n個頂點(最多有n個頂點入度為0,因為圖總共有n個頂點) for(i = 0; i<GL->numVertexes; i++) if(GL->adjList[i].in == 0)??/*將入度為0的頂點入棧*/ stack[++top] = i; top2 = 0; etv = (int*)?malloc(GL->numVertexes*sizeof(int));??/*事件的最早發生時間*/ for(i=0;i<GL->numVertexes; i++) etv[i] = 0; stack2 = (int*)?malloc(GL->numVertexes*sizeof(int));?/*初始化*/ while(top != 0) { gettop = stack[top--];??/*出棧*/ printf("%d -> ",GL->adjList[gettop].data);?/*打印此頂點*/ stack2[++top2] = gettop;??/*將彈出的頂點序列號壓入拓撲序列的棧中*/ count++;?/*統計輸出頂點數*/ for(e=GL->adjList[gettop].firstedge; e; e=e->next) {?/*對此頂點弧表遍歷*/ k = e->adjvex; if(--GL->adjList[k].in == 0)??//將k號頂點鄰接點的入度減1,且減1后,入度為0的頂點需要存到棧中 stack[++top] = k; if((etv[gettop]+e->weight)>etv[k])?/*求各頂點時間最早發生時間*/ etv[k] = etv[gettop] + e->weight;??/*某個頂點的最早發生時間= 和他相關的活動必須全部完成*/ } } if(count < GL->numVertexes)??/*如果count小于頂點數,說明存在環*/ return?-1; else return?0; } /*求關鍵路徑,GL為有向網,輸出GL的各項關鍵活動*/ void?CriticalPath(GraphAdjList GL) { EdgeNode *e; int?i,gettop,k,j; int?ete,lte;????/*聲明活動最早發生時間和最遲發生時間*/ TopoLogicalSort(GL);??/*求拓撲序列,計算數組etv和stack2的值*/ ltv = (int*)?malloc(GL->numVertexes*sizeof(int));?/*時間的最晚發生時間*/ for(i= 0; i<GL->numVertexes;i++) ltv[i]=etv[GL->numVertexes-1];??/*初始化ltv[i] 為工程完成的最早時間,etv[i]初始化為0*/ while(top2!=0)??/*計算ltv*/ { gettop = stack2[top2--]; for(e=GL->adjList[gettop].firstedge;e!=NUll;e=e->next) {/*求各定點事件的最遲發生時間ltv值*/ k=e->adjvex; if(ltv[k]-e->weight<ltv[gettop]) ltv[gettop]= ltv[k]-e->weight;???/*求最晚發生時間,是從拓撲序列的最后一個頂點逆著推導*/ } } for(j=0;j<GL->numVertexes;j++)??/*求關鍵活動*/ { for(e=GL->adjList[j].firstedge;e!=NULL;e=e->next) { k=e->adjvex; ete = etv[j];???/*活動最早開始時間*/ lte = ltv[k] - e->weight;/*活動最晚發生時間*/ if(ete ==lte) printf("<v%d,v%d> length: %d, ",GL->adjList[j].data,GL->adjList[k].data,e->weight); } } }

總結

以上是生活随笔為你收集整理的拓扑排序--关键路径的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。