一、慢速并查集
对于每个并集运算,要搜索所有的对象,所以速度较慢
由下图可以看出,就是把所有的相同的集合都赋值为一样,就表示相同的集合;每个对象只有一个父节点
#include<stdio.h>
#define N 10000
int main()
{
int i,p,q,t,id[N];
for(i = 0;i < N;i++)
id[i] = i;
while(scanf("%d %d",&p,&q) == 2)
{
if(id[p] == id[q]) continue;
else
{
t = id[p];
for(i = 0;i < N;i++)
{
if(id[i] == t)
id[i] = id[q];
}
}
printf("%d %d\n",id[p],id[q]);
}
return 0;
}
性质1-1 对于N个对象,每个对象包括M个并集运算的连通性问题,使用快速查找(慢速并集)算法至少要执行MN条指令,因为对于M个并集运算,每个运算要迭代for循环N次
二、快速并查集通过指针的引用实现快速查找;并集的运算计算量少(只用一次),查找运算计算量大(要不断的搜索父节点)
#include<stdio.h>
#define N 10000
int main()
{
int i,j,p,q,t,id[N];
for(i = 0;i < N;i++)
id[i] = i;
while(scanf("%d %d",&p,&q) == 2)
{
for(i = p;i != id[i]; i = id[i]);//寻找左边的父节点
for(j = q;j != id[j]; j = id[j]);//寻找右边的父节点
if(i == j)
continue;
id[i] = j;
printf("%d %d\n",id[p],id[q]);
}
return 0;
}
性质1-2 若M>N 快速并集算法可能要运行多于M*N/2条指令(主要是平均查找高度)解决一个拥有N个对象、M个对的连通性问题
三、加权快速并集运算(解决1-2的不利事件)
//将树的高度降低,连接两棵树中较小树的根与较大树的根的结果,每个节点与树根的距离短,所以查找效率高
性质1-3 加权快速并集算法最多只要跟踪2*lgN个指针
所以增加一个数组保存节点数,防止树中长路径的增长。代码为:
#include<stdio.h>
#define N 10000
int main()
{
int i,j,p,q,t,id[N];
int sz[N];//记录
for(i = 0;i < N;i++)
{
id[i] = i;
sz[i] = 1;
}
while(scanf("%d %d",&p,&q) == 2)
{
for(i = p;i != id[i]; i = id[i]);//寻找左边的父节点
for(j = q;j != id[j]; j = id[j]);//寻找右边的父节点
if(i == j)
continue;
if(sz[i] < sz[j])
{
//小根连接大根 这样子就不容易增长
id[i] = j;
//只需要关注最终集合即可,原来的集合已经被包含了
sz[j] += sz[i];
}
else
{
id[j] = i;
sz[i] += sz[j];
}
printf("%d %d\n",p,q);
}
}
问题:能否确保具有线性性能的算法?这是一个难以回答的问题
但是有很多容易的方法可以进一步改进加权并集算法,理想情况下,希望每个节点直接指向树的根节点
可以采用路径压缩!
路径压缩:在并集运算中,添加另一遍次经过每条路径,将路径中对应每个顶点的ID项设置成指向根。最终结果是几乎把树压平。
四:对分路径压缩
#include<stdio.h>
#define N 10000
int main()
{
int i,j,p,q,t,id[N];
int sz[N];//记录
for(i = 0;i < N;i++)
{
id[i] = i;
sz[i] = 1;
}
while(scanf("%d %d",&p,&q) == 2)
{
for(i = p;i != id[i]; i = id[i])//寻找左边的父节点
id[i] = id[id[i]];
for(j = q;j != id[j]; j = id[j]);//寻找右边的父节点
id[j] = id[id[j]];
if(i == j)
continue;
if(sz[i] < sz[j])
{
//小根连接大根 这样子就不容易增长
id[i] = j;
//只需要关注最终集合即可,原来的集合已经被包含了
sz[j] += sz[i];
}
else
{
id[j] = i;
sz[i] += sz[j];
}
printf("%d %d\n",p,q);
}
}
几种方法的对比:(其中方法4在练习中)