資料結構學習(C++)——圖【5】活動網路(AOV、AOE) (轉)
這部分是和工程相關的,也就是說,當AOV、AOE很複雜的時候,才能顯示出這部分的價值——簡單的話,手工都要比快,輸入資料那段時間手工結果就出來了。我也沒什麼例子好舉,總給我一種沒底氣的感覺,勉為其難的把程式寫完就算完事吧。和前邊的相比,這部分專業了一點,換而言之,不是每個人都感興趣,不想看就跳過去吧。
活動主要有兩個演算法,拓撲排序和求關鍵路徑,後者以前者為基礎。仿照上篇,另外構造一個“演算法類”,需要演算法時,將圖繫結到演算法上。
#includework.h"
#define iterator list::edge>::iterator
#define begin(i) G->data.vertices[i].e->begin()
#define end(i) G->data.vertices[i].e->end()
struct CriAct
{
CriAct() {}
CriAct(int , int dest) : s(source), d(dest) {}
int s, d;
};
template
class ActivityNetwork
{
public:
ActivityNetwork(Network
{
count = new int[N]; result = new int[N];
}
~ActivityNetwork()
{
delete []count; delete []result;
}
const vector
const int* out;
private:
void initialize()
{
for (int j = 0; j < N; j++) count[j] = 0;
for (int i = 0; i < N; i++)
{
for (iterator iter = begin(i); iter != end(i); iter++) count[iter->vID]++;
}
out = result;
}
Network
vector
int N, *count, *result;
};
因為AOV和AOE的邊都不會太多(想象一下邊多的情況,那事件就都是雞毛蒜皮了),所以儲存結構直接選擇了鄰接表。並且為了體現鄰接表的優勢,需要直接操作私有資料,因此要把這個類宣告為Link類和Network類的友元,另外由於這個類在後面,所以需要前視宣告。具體如下:
template
template
{friend class ActivityNetwork
template
{ friend class ActivityNetwork
這個演算法很精巧,避免了對已經排好序的頂點的再次掃描,另外,殷版上用計數陣列來充當棧的方法也很巧妙。演算法的說明參閱相關的教科書,不再贅述。
bool TopoSort()
{
initialize(); int i, top = -1;
for (i = 0; i < N; i++) if (!count[i]) { count[i] = top; top = i; }
for (i = 0; i < N; i++) //TopoSort Start:namespace prefix = o ns = "urn:schemas--com::office" />
{
if (top == -1) return false;
result[i] = top; top = count[top];
for (iterator iter = begin(result[i]); iter != end(result[i]); iter++)
if (!--count[iter->vID]) { count[iter->vID] = top; top = iter->vID; }
}
return true;
}
由於public資料成員out和private資料成員result指向同一個陣列,在類的外面可以透過out來得到排序結果,只是不能改變(當然,非要改變const資料也不是沒有辦法)。下面是測試程式,資料來自殷版:
#include
using namespace std;
#include "ActivityNetwork.h"
int main()
{
Network
a.insertV(0);a.insertV(1);a.insertV(2);a.insertV(3);a.insertV(4);a.insertV(5);
a.insertE(0,3,1);a.insertE(0,1,1);a.insertE(1,5,1);a.insertE(2,1,1);
a.insertE(2,5,1);a.insertE(4,0,1);a.insertE(4,1,1);a.insertE(4,5,1);
ActivityNetwork
if (b.TopoSort()) for (int i = 0; i < a.vNum(); i++) cout << b.out[i] << ' ';
return 0;
}
有了拓撲排序的結果,這個程式就比較好寫了,那些所謂的“技巧”就不用了,如下的程式,很直白,演算法說明請參考教科書。
bool CriPath()
{
if (!TopoSort()) return false; int i; iterator iter; CA.clear();
dist* Ve = new dist[N]; dist* Vl = new dist[N];//Ve最早開始時間,Vl最遲開始時間
for (i = 0; i < N; i++) Ve[i] = 0;//Ve初始化
for (i = 0; i < N; i++)//按拓撲順序計算Ve
for (iter = begin(result[i]); iter != end(result[i]); iter++)
if (Ve[result[i]]+iter->cost>Ve[iter->vID]) Ve[iter->vID]= Ve[result[i]] + iter->cost;
for (i = 0; i < N; i++) Vl[i] = Ve[N - 1];//Vl初始化
for (i = N - 2; i >= 0; i--)//按逆拓撲順序計算Vl
for (iter = begin(result[i]); iter != end(result[i]); iter++)
if (Vl[iter->vID]-iter->cost < Vl[result[i]]) Vl[result[i]] = Vl[iter->vID] - iter->cost;
for (i = 0; i < N; i++)//計算各個活動的最早開始時間和最遲開始時間
for (iter = begin(i); iter != end(i); iter++)
if (Ve[i] == Vl[iter->vID] - iter->cost) CA.push_back(CriAct(i, iter->vID));
return true;
}
同樣的在類的外面可以透過outCriAct得到結果,是一個const引用。如下的測試程式,資料來自殷版:
#include
using namespace std;
#include "ActivityNetwork.h"
int main()
{
Network
a.insertV(0);a.insertV(1);a.insertV(2);a.insertV(3);a.insertV(4);
a.insertV(5); a.insertV(6);a.insertV(7);a.insertV(8);
a.insertE(0,1,6);a.insertE(0,2,4);a.insertE(0,3,5);
a.insertE(1,4,1);a.insertE(2,4,1);a.insertE(3,5,2);
a.insertE(4,6,9);a.insertE(4,7,7);a.insertE(5,7,4);
a.insertE(6,8,2);a.insertE(7,8,4);
ActivityNetwork
if (b.CriPath())
for (int j = 0; j < b.outCriAct.size(); j++)
cout <' << ' ';
return 0;
}
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-962171/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 資料結構學習(C++)——圖(總結) (轉)資料結構C++
- 資料結構學習(C++)——圖【3】(無向圖)(上) (轉)資料結構C++
- 資料結構學習(C++)——圖【3】(無向圖)(下) (轉)資料結構C++
- 資料結構學習(C++)——序言 (轉)資料結構C++
- 資料結構學習(C++)——圖【4】(最短路徑) (轉)資料結構C++
- 資料結構學習(C++)——圖【2】(DFS和BFS) (轉)資料結構C++
- 資料結構學習(C++)——樹(總結) (轉)資料結構C++
- 資料結構學習(C++)——圖【1】(基本儲存方法) (轉)資料結構C++
- 資料結構學習(C++)——遞迴【1】 (轉)資料結構C++遞迴
- 資料結構學習(C++)——迴圈連結串列 (轉)資料結構C++
- 資料結構學習(C++)——雙向連結串列 (轉)資料結構C++
- 資料結構學習(c++)——二叉樹 (轉)資料結構C++二叉樹
- 資料結構學習(C++)——遞迴【2】(1) (轉)資料結構C++遞迴
- 資料結構學習(C++)——遞迴【2】(2) (轉)資料結構C++遞迴
- 資料結構學習(C++)——遞迴【2】(3) (轉)資料結構C++遞迴
- 資料結構學習(C++)——遞迴【2】(4) (轉)資料結構C++遞迴
- 資料結構學習(C++)——遞迴【3】(1) (轉)資料結構C++遞迴
- 資料結構學習(C++)——遞迴【3】(2) (轉)資料結構C++遞迴
- 資料結構學習總結--圖資料結構
- 資料結構學習(C++)——二叉樹【2】 (轉)資料結構C++二叉樹
- 資料結構學習(C++)續——排序【3】交換排序 (轉)資料結構C++排序
- 資料結構學習(C++)——二叉樹【3】 (轉)資料結構C++二叉樹
- 資料結構學習(C++)——二叉樹【1】 (轉)資料結構C++二叉樹
- 演算法與資料結構學習路線圖演算法資料結構
- 資料結構學習(C++)——棧應用(表示式求值) (轉)資料結構C++
- 資料結構學習(C++)續——排序【2】插入排序 (轉)資料結構C++排序
- 資料結構學習(C++)續——排序【1】測試程式 (轉)資料結構C++排序
- 資料結構學習(C++)續——排序【6】內部排序總結 (轉)資料結構C++排序
- 資料結構學習(C++)——線性鏈式結構總結(代後記)【1】 (轉)資料結構C++
- 資料結構學習(C++)——線性鏈式結構總結(代後記)【2】 (轉)資料結構C++
- 收藏資料結構學習網站資料結構學習網站
- 資料結構學習(C++)——單連結串列(定義與實現) (轉)資料結構C++
- 資料結構學習筆記(一) (轉)資料結構筆記
- 資料結構學習(C++)——稀疏矩陣(十字連結串列【2】) (轉)資料結構C++矩陣
- 資料結構學習(C++)——稀疏矩陣(十字連結串列【1】) (轉)資料結構C++矩陣
- C++資料結構和pb資料結構的轉換C++資料結構
- 資料結構學習資料結構
- 資料結構學習(C++)——棧和佇列(定義和實現) (轉)資料結構C++佇列