并查集的“并优化”(leader合并)和“查优化”(路径压缩)
2015-06-22 16:45
375 查看
在博文http://blog.csdn.net/stpeace/article/details/46506861中, 我们已经详细地了解了并查集, 不过, 那个程序略显粗糙, 下面我们考虑来优化一下。
先给出没有优化的代码吧:
YES
YES
YES
YES
YES
YES
NO
NO
NO
NO
NO
NO
4
实际上, 在findLeader的时候, 我们可以进行路径压缩, 这是“查优化”的关键点。而在并的过程中, 也可以进行“并优化”, 不过, “并优化”的作用不太明显, 如下:
YES
YES
YES
YES
YES
YES
NO
NO
NO
NO
NO
NO
4
如果还有理解不清楚的, 请参考我之前的博文http://blog.csdn.net/stpeace/article/details/46506861
先给出没有优化的代码吧:
// taoge的并查集 #include <iostream> using namespace std; #define N 1000 int leader[N + 1] = {0}; // 先搞一个充分大的数组 // 初始化 void setLeader() { int i = 1; for(i = 1; i <= N; i++) { leader[i] = i; // 初始化时, 将自己初始化为自己的领导 } } // 查找领导, 看看究竟是谁(实际上, 还可以进行路径压缩优化) int findLeader(int n) { int r = n; while(leader[r] != r) { r = leader[r]; // 没找到的话, 一直往上找 } return r; } // 将两个领导带领的团队融合, 从此, leaderX和leaderY建立了新的统一战线, 是一个大家庭团队了 void uniteSet(int leaderX, int leaderY) { leader[leaderX] = leaderY; // leader[leaderY] = leaderX; } // 输入数组, 每一行表示一个集合关系, 比如第一行表示3和4属于一个集合团队 int input[] = { 3, 4, 4, 2, 7, 6, 5, 1, 3, 9, 11, 8, 6, 10, 9, 13, 11, 12, }; // 测试数组, 测试每行的两个整数是否属于同一个大的家庭团队 int test[] = { 3, 2, 9, 4, 7, 10, 6, 7, 13, 4, 8, 12, 6, 9, 4, 7, 11, 10, 1, 2, 12, 13, 7, 13, }; int main() { int numberOfSets = 13; // 总共有13个元素, 即1, 2, 3, 4, ...., 13 // 初始化领导 setLeader(); int i = 0; int j = 0; int n = sizeof(input) / sizeof(input[0]) / 2; for(j = 0; j < n; j++) { int u = input[i++]; int v = input[i++]; // 找领导 u = findLeader(u); v = findLeader(v); // 领导不相等, 则融合着两个团队, 合二为一 if(u != v) { uniteSet(u, v); numberOfSets--; } } i = 0; n = sizeof(test) / sizeof(test[0]) / 2; for(j = 0; j < n; j++) { int u = test[i++]; int v = test[i++]; // 找领导 u = findLeader(u); v = findLeader(v); // 如果领导不相同, 则不属于一个团队; 如果两个领导相同, 则肯定属于一个团队 if(u != v) { cout << "NO" << endl; } else { cout << "YES" << endl; } } // 其实, 经合并后, 最后的集合是4个: // {3, 4, 2, 9, 13}, {7, 6, 10,}, {5, 1}, {11, 8, 12} cout << numberOfSets << endl; return 0; }结果为:
YES
YES
YES
YES
YES
YES
NO
NO
NO
NO
NO
NO
4
实际上, 在findLeader的时候, 我们可以进行路径压缩, 这是“查优化”的关键点。而在并的过程中, 也可以进行“并优化”, 不过, “并优化”的作用不太明显, 如下:
// taoge的并查集 #include <iostream> using namespace std; #define N 1000 int leader[N + 1] = {0}; // 先搞一个充分大的数组 // 初始化 void setLeader() { int i = 1; for(i = 1; i <= N; i++) { leader[i] = i; // 初始化时, 将自己初始化为自己的领导 } } // 查找领导, 看看究竟是谁 int findLeader(int n) { int r = n; while(leader[r] != r) { r = leader[r]; // 没找到的话, 一直往上找 } // "查优化"的本质是路径压缩, 最终使得所有员工的直接上司均为该组的leader int i = n; int j = 0; while(i != r) { j = leader[i]; leader[i] = r; i = j; } return r; } // 将两个领导带领的团队融合, 从此, leaderX和leaderY建立了新的统一战线, 是一个大家庭团队了 void uniteSet(int leaderX, int leaderY) { // 我个人认为:"并优化"的作用不是很大 if(leaderX < leaderY) { leader[leaderX] = leaderY; } else { leader[leaderY] = leaderX; } } // 输入数组, 每一行表示一个集合关系, 比如第一行表示3和4属于一个集合团队 int input[] = { 3, 4, 4, 2, 7, 6, 5, 1, 3, 9, 11, 8, 6, 10, 9, 13, 11, 12, }; // 测试数组, 测试每行的两个整数是否属于同一个大的家庭团队 int test[] = { 3, 2, 9, 4, 7, 10, 6, 7, 13, 4, 8, 12, 6, 9, 4, 7, 11, 10, 1, 2, 12, 13, 7, 13, }; int main() { int numberOfSets = 13; // 总共有13个元素, 即1, 2, 3, 4, ...., 13 // 初始化领导 setLeader(); int i = 0; int j = 0; int n = sizeof(input) / sizeof(input[0]) / 2; for(j = 0; j < n; j++) { int u = input[i++]; int v = input[i++]; // 找领导 u = findLeader(u); v = findLeader(v); // 领导不相等, 则融合着两个团队, 合二为一 if(u != v) { uniteSet(u, v); numberOfSets--; } } i = 0; n = sizeof(test) / sizeof(test[0]) / 2; for(j = 0; j < n; j++) { int u = test[i++]; int v = test[i++]; // 找领导 u = findLeader(u); v = findLeader(v); // 如果领导不相同, 则不属于一个团队; 如果两个领导相同, 则肯定属于一个团队 if(u != v) { cout << "NO" << endl; } else { cout << "YES" << endl; } } // 其实, 经合并后, 最后的集合是4个: // {3, 4, 2, 9, 13}, {7, 6, 10,}, {5, 1}, {11, 8, 12} cout << numberOfSets << endl; return 0; }结果同样是:
YES
YES
YES
YES
YES
YES
NO
NO
NO
NO
NO
NO
4
如果还有理解不清楚的, 请参考我之前的博文http://blog.csdn.net/stpeace/article/details/46506861
相关文章推荐
- PATBasic——1012. 数字分类 (20)
- 第十六周 阅读程序
- MyEclipse10.6 myeclipse2013下添加jadClipse反编译插件 .
- 分数减法
- 一步步搭建自己的轻量级MVCphp框架-(三)一个国产轻量级框架Amysql源码分析(2) 进程
- [.net 面向对象编程基础] (23) 结束语
- 【图像处理】数字图像处理软件(二)
- 工作周记
- 问题的迷思
- sublime text 2的汉化
- ACM输入输出--多组测试用例--C、C++、Java
- ImageView的scaletype属性
- struts2源码调试环境的搭建
- 【Unity3d】热更新Assetbundle资源以及需要注意的地方
- 安卓加载网页
- 利用Redis设计秒杀原理
- 认知、流形与虚实世界
- 重构是每个程序员的洗髓经
- exploit - stack overflow with seh
- poj 1606 Jugs