并集-查找算法

用于判断图中节点对的连通性

快速查找:
#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);
    }
}
算法性能理想

转载于:https://www.cnblogs.com/ArthurSJiang/archive/2012/08/18/2645467.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值