《算法: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
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?