数据结构-并查集

看图可以从这篇博客看,我不会画图。但是大体意思差不多

https://blog.csdn.net/u013486414/article/details/38682057

#include <iostream>
#include <algorithm>
#include <math.h>
using namespace std;
int a[10000];
int n;
int sz[1000];//从tunion3开始使用,标记没颗树的个数
int heigh[1000];//表示数的层数
void init(){
    for(int i=0;i<n;i++){
        //并查集最大的亮点就是当a[i]==i的时候表示是 根,以自身为根
        a[i]=i;
        sz[i]=1;//标记初始的时候,每棵树大小都是1
        heigh[i]=1;//标记初始的时候,每棵树的层数都是1
    }
}
int find1(int x){
    return a[x];
}
void tunion1(int x,int y){
    //找出根节点
   int px=find1(x);
   int py=find1(y);
   if(px==py)
    return;
   for(int i=0;i<n;i++){//这个遍历的地方比较耗时
        if(a[i]==px)
        {
            a[i]=py;
        }
   }
}
int find2(int xRoot){//这种方式,可能是某一个树太长,回溯找根浪费时间
    while(xRoot!=a[xRoot])
    {//不停的指向上直到找到自己的根节点
        xRoot=a[xRoot];
    }
    return xRoot;//返回根节点
}
void tunion2(int x,int y){
   int pxRoot=find2(x);
   int pyRoot=find2(y);
   if(pxRoot==pyRoot)
    return;
   //将以a[px]为根的树移动到以py为节点下
   a[pxRoot]=pyRoot;
}
int find3(int xRoot){//这种方式,可能是某一个树太长,回溯找根浪费时间
    while(xRoot!=a[xRoot])
    {//不停的指向上直到找到自己的根节点
        xRoot=a[xRoot];
    }
    return xRoot;//返回根节点
}
//将元素少的并入元素多的,可能会使层数变小
void tunion3(int x,int y){
   int pxRoot=find3(x);
   int pyRoot=find3(y);
   if(pxRoot==pyRoot)
    return;
   //将以a[px]为根的树移动到以py为节点下
   if(sz[pxRoot]<=sz[pyRoot]){
        a[pxRoot]=pyRoot;
        sz[pyRoot]+=sz[pxRoot];
   }else{
    a[pyRoot]=pxRoot;
    sz[pxRoot]+=sz[pyRoot];
   }

}
int find4(int xRoot){//这种方式,可能是某一个树太长,回溯找根浪费时间
    while(xRoot!=a[xRoot])
    {//不停的指向上直到找到自己的根节点
        xRoot=a[xRoot];
    }
    return xRoot;//返回根节点
}
//将元素少的并入元素多的,可能会使层数变小
void tunion4(int x,int y){
   int pxRoot=find4(x);
   int pyRoot=find4(y);
   if(pxRoot==pyRoot)
    return;
   //将以a[px]为根的树移动到以py为节点下,寻找父节点
   if(heigh[pxRoot]<heigh[pyRoot]){
        a[pxRoot]=pyRoot; //就算将一棵树移到另一颗树下,那么他的层数顶多和pyRoot的相同
   }else if(heigh[pxRoot]>heigh[pyRoot]){
        a[pyRoot]=pxRoot;//同理
   }else{//heigh[pxRoot]==heigh[pyRoot]
        a[pyRoot]=pxRoot;
        heigh[pxRoot]++;
   }

}
//路径压缩,但是这一种,是一层一层的网父亲的父亲上移动
int find5(int x){
    while(x!=a[x]){
        a[x]=a[a[x]];
        x=a[x];
    }
    return x;
}
//递归版的路径压缩,压缩成每个树的层数就只有2层
int find5digui(int x){
    if(x!=a[x]){
        a[x]=find5digui(a[x]);
    }
    return a[x];
}
//非递归下的路径压缩,树的层数还是必须得要的
int find5feidigui(int x){
    int k,j,r;
    r=x;
    while(r!=a[r]){
        r=a[r];//找出根节点
    }
    k=x;
    while(k!=r){ // 非递归路径压缩,从x开始的每一个parent节点都指向根节点
        j=a[k]; // j暂存父节点
        a[k]=r;// 父节点指向根节点
        k=j;// k移到父节点
    }
    return r; //返回根节点的值
}
void tunion5(int x,int y){
   int pxRoot=find5(x);
   int pyRoot=find5(y);
   if(pxRoot==pyRoot)
    return;
   //将以a[px]为根的树移动到以py为节点下,寻找父节点
   if(heigh[pxRoot]<heigh[pyRoot]){
        a[pxRoot]=pyRoot; //就算将一棵树移到另一颗树下,那么他的层数顶多和pyRoot的相同
   }else if(heigh[pxRoot]>heigh[pyRoot]){
        a[pyRoot]=pxRoot;//同理
   }else{//heigh[pxRoot]==heigh[pyRoot]
        a[pyRoot]=pxRoot;
        heigh[pxRoot]++;
   }

}
/**
*
*并查集的五种形式。从简单到路径压缩 用例0 1 2 3 4
* 1 2 ,1 3, 3 4 三组样例测试
*/
int main()
{
    while(cin>>n){
        if(n==0) break;
        //memset(a,sizeof(a),0);
        init();
        int x,y,m;
        cin>>m;
        while(m--){//这个地方是设置那两个点是连接的
            cin>>x>>y;
            //tunion1(x,y);//quick find
            //tunion2(x,y);//这个是随便构成一个树,无限层的连接
            //tunion3(x,y);//这个是看元素的个数,谁的元素少那就并向谁
            //tunion4(x,y);//这个是看层数,谁的层数小就并上谁
            tunion5(x,y);//路径压缩
        }
        int ans=0;
        for(int i=0;i<n;i++){
            cout<<a[i]<<" "<<endl;
            if(a[i]==i)
                ans++;
        }
        cout<<endl;
        //有几棵树
        cout<<ans<<endl;
        //有几条线就能联通
        cout<<ans-1<<endl;
    }

}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值