树状合并、带路径压缩的并查集可以以最大O(logN),平均O(1)的复杂度完成合并与测试操作
这个是2006年8月8日更新版,相比于2006年7月8日版,有以下改进:
1、添加求集合规模运算
2、简化代码
3、提高运行速度
4、减少占用空间
该标程经VC6.0及g++编译器编译通过
#include
<
cstring
>
namespace
UnionNS
{
![](https://i-blog.csdnimg.cn/blog_migrate/0263e0c3f9f3faecf5b4177968c5d64c.gif)
/**/ /* 解决:并查集
*算法:树状、带路径压缩的并查集
*备注:by Cockerel 06-08-08
*/
const int maxV = 100 ;
int p[maxV]; // p[i]= p[i]>=0 ? 父编号 : 集合规模
// 初始化:
inline void init( int v)
{
memset(p, - 1 , sizeof (p)); // 初始化为根且规模为1
}
// 求根运算:
inline int root( int i)
{
int r;
for (r = i; p[r] >= 0 ; r = p[r]);
for (; i != r; i = p[i])
p[i] = r; // 路径压缩
return r;
}
// 判断等价
inline bool equal( int i, int j)
{
return root(i) == root(j);
}
// 求集合规模
inline size( int i)
{
return - p[root(i)];
}
// 合并
inline merge( int i, int j)
{
i = root(i); j = root(j);
if (p[i] < p[j]) // 树状合并
p[i] += p[j], p[j] = i;
else
p[j] += p[i], p[i] = j;
}
}
//
测试程序
#include
<
cstdio
>
namespace
UnionNS
{
char file[] = " unionIn.txt " ;
![](https://i-blog.csdnimg.cn/blog_migrate/0263e0c3f9f3faecf5b4177968c5d64c.gif)
void test()
{
char c;
int v,u,w;
scanf( " %c " , & c);
![](https://i-blog.csdnimg.cn/blog_migrate/0263e0c3f9f3faecf5b4177968c5d64c.gif)
switch (c)
{
case ' P ' :
scanf( " %d " , & v);
printf( " init: %d/n " ,v);
init(v);
break ;
case ' T ' :
scanf( " %d %d " , & u, & w);
printf(equal(u,w) ? " %d & %d: same/n " : " %d & %d: different/n " , u,w);
break ;
case ' U ' :
scanf( " %d %d " , & u, & w);
printf( " union %d & %d/n " ,u,w);
merge(u,w);
break ;
}
}
}
using
namespace
UnionNS;
![](https://i-blog.csdnimg.cn/blog_migrate/17c135a2763225eb253f4ff92e88a664.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/353c1fa9cd42287d30310af820b5430d.gif)
int
main()
{
freopen(file, " r " ,stdin);
while ( ! feof(stdin))
test();
return 0 ;
}