《算法:C语言实现》——连通性
/* 主题: 连通性问题 * 问题表述: 给定整数对的一个序列,其中每个整数表示某种类型的一个对象,我们想要说明对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