/* 主題: 連通性問題 * 問題表述: 給定整數對的一個序列,其中每個整數表示某種類型的一個對象,我們想要說明對p-q表示“p連結到q”。 * “連通”關係是可傳遞的,即p-q,q-r,則p-r。我們的目標是寫一個過濾集合中的無關對的程式。程式的 * 輸入為p-q,如果已經看到的到那點的數對並不隱含著p連通到q,那麼輸出該對。如果前面的對確實隱含 * 著p連通到q,那麼程式應該忽略p-q,並應該繼續輸入下一對。 * 開發語言: C++ * 編譯器: g++ * 作者: chinazhangjie * 郵箱: chinajiezhang@gmail.com * 參考書籍: 《演算法: C語言實現(第1~4部分)》 * * 測試資料: * 對象: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 * 邊: 3-4, 4-9, 8-0, 2-3, 5-6, 2-9, 5-9, 7-3, 4-8, 5-6, 0-2, 6-1 */#include <iostream>#include <vector>#include <string>#include <iterator>using namespace std;const int objectCount = 10;const int lineCount = 12;struct Line{ int left; int right;public: Line (int l, int r) : left(l), right(r) {} Line () {}};void PrintObject(const vector<int> & object, const string& prompt = string(""));// 快速尋找演算法。為了要與其他演算法用一份來源資料,所以在計算之前,複製一份資料void QuickFind(const vector<int> & object, const vector<Line> & line){ vector<int> aObject(object); // a for assist vector<Line> aLine(line); for (int i=0; i<(int)aLine.size(); ++i) { if (aObject[aLine[i].left] == aObject[aLine[i].right]) continue; int temp = aObject[aLine[i].left]; for (int j=0; j<(int)aObject.size(); ++j) { if (aObject[j] == temp) aObject[j] = aObject[aLine[i].right]; } } PrintObject(aObject, "QuickFind");}// 快速合并演算法void QuickMerge(const vector<int> & object, const vector<Line> & line){ vector<int> aObject(object); vector<Line> aLine(line); for (int i=0; i<(int)aLine.size(); ++i) { int j; int k; for (j=aObject[aLine[i].right]; j != aObject[j]; j = aObject[j]) ; for (k=aObject[aLine[i].left]; k != aObject[k]; k = aObject[k]) ; if (j == k) continue; aObject[k] = j; } PrintObject(aObject, string("QuickMerge"));}// 加權快速合并演算法。增加一個數組記錄每棵樹的結點個數,每次合并的時候將較小的樹串連到較大的樹上,以防止樹中長度路徑的增長void WeightedQuickMerge(const vector<int> & object, const vector<Line> & line){ vector<int> aObject(object); vector<Line> aLine(line); vector<int> nodeCount(objectCount, 1); for (int i=0; i<(int)aLine.size(); ++i) { int j; int k; for (j=aObject[aLine[i].right]; j != aObject[j]; j = aObject[j]) ; for (k=aObject[aLine[i].left]; k != aObject[k]; k = aObject[k]) ; if (j == k) continue; if (nodeCount[j] < nodeCount[k]) { aObject[j] = k; nodeCount[j] += nodeCount[k]; } else { aObject[k] = j; nodeCount[k] += nodeCount[j]; } } PrintObject(aObject, string("WeightedQuickMerge"));}// 等分路徑壓縮void SplitPathCompress(const vector<int> & object, const vector<Line> & line){ vector<int> aObject(object); vector<Line> aLine(line); for (int i=0; i<(int)aLine.size(); ++i) { int j; int k; for (j=aObject[aLine[i].right]; j != aObject[j]; j = aObject[j]) { aObject[j] = aObject[aObject[j]]; } for (k=aObject[aLine[i].left]; k != aObject[k]; k = aObject[k]) { aObject[k] = aObject[aObject[k]]; } } PrintObject(aObject, string("SplitPathCompresse"));}// 列印資料void PrintObject(const vector<int> & object, const string& prompt){ cout << prompt << ": "; copy(object.begin(), object.end(), ostream_iterator<int>(cout, " ")); cout << endl;}int main(){ // init vector<int> object(objectCount); for (int i=0; i<objectCount; ++i) { object[i] = i; } vector<Line> line; line.push_back(Line(3, 4)); line.push_back(Line(4, 9)); line.push_back(Line(8, 0)); line.push_back(Line(2, 3)); line.push_back(Line(5, 6)); line.push_back(Line(2, 9)); line.push_back(Line(5, 9)); line.push_back(Line(7, 3)); line.push_back(Line(4, 8)); line.push_back(Line(5, 6)); line.push_back(Line(0, 2)); line.push_back(Line(6, 1)); // QuickFind(object, line); QuickMerge(object, line); WeightedQuickMerge(object, line); SplitPathCompress(object, line); return 0;}
本文完
轉載註明出處,謝謝!
2011-06-22