并集-查找算法
用于判断图中节点对的连通性
快速查找:
#include<stdio.h>
#define N 10000
main()
{
int i,p,q,t,id[N];
for(i=0;i<N;i++) id[i]=i;
while(scanf("%d%d\n",&p,&q)==2)
{
if(id[p]==id[q]) continue;
for(t=id[p],i=0;i<N;i++)
if(id[i]==t) id[i]=id[q];
printf("%d %d\n",p,q);
}
}
优点:查找操作只需查看数组中的值是否相等
缺点:每次做并集操作需遍历整个数组
快速并集:
#include<stdio.h>
#define N 10000
main()
{
int i,j,p,q,id[N];
for(i=0;i<N;i++) id[i]=i;
while(scanf("%d%d\n",&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",p,q);
}
}
优点:并集操作很快,查找需依赖输入特性生成的树的扁平情况
缺点:树可能退化成单链表,例如:输入样例1-2,2-3,3-4,4-5...
加权快速并集:
#include<stdio.h>
#define N 10000
main()
{
int i,j,p,q,id[N],sz[N];//sz[N]用来记录每个集合中的节点个数
for(i=0;i<N;i++)
{
id[i]=i;
sz[i]=1;
}
while(scanf("%d%d\n",&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);
}
}
算法性能理想
对分路径压缩加权快速并集:
#include<stdio.h>
#define N 10000
main()
{
int i,j,p,q,id[N],sz[N];//sz[N]用来记录每个集合中的节点个数
for(i=0;i<N;i++)
{
id[i]=i;
sz[i]=1;
}
while(scanf("%d%d\n",&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);
}
}
算法性能理想
好久没写博客了,想把过去在各个地方写的东西先搬过来,目前的主要工作就是“搬家”。