并查集总结

并查集
一、定义
并查集是一种树型的数据结构,用于处理一些不相交集合的合并及查询问题
集合定义方法:“代表元法”,每个集合选择一个节点作为整个集合的代表,最根部的父亲节点
二、基本操作
Find——查询一个元素属于哪一个集合
Merge——把两个集合合并成一个大集合
三、常规操作、路径压缩与按秩合并

初始化
一开始初始化将每个节点所在集合的代表节点都设为自己

for(int i=1;i<=n;i++)
{
	f[i]=i;
}

Find函数
查询当前节点所在集合的代表节点(根节点)

int find(int x){
	return f[x] == x ? x : find(f[x]);
}

常规合并
如果不是同一个集合,就将x整个集合插入y集合当做一个子节点

void merge (int x,int y) {
	int n, m;
	n = Find (parent, x);
	m = Find (parent, y);
	if (m != n) {
		f[n] = m;
	}
}

路径压缩
将访问过的节点直接指向树根,均摊复杂度

int find(int x) { return x == f[x] ? f[x] : f[x] = find(f[x]); }

按秩合并

“秩”:树的深度(未路径压缩) / 集合大小 。均摊复杂度
将”秩“记录在 “代表元素” ,合并时,将“秩”较小的树根 作为“秩”较大的树根的子节点

void unionn(int x, int y){//按大小合并
    int u=Get(x), v=Get(y);
    if(u != v) {
        if(size[u]<size[v]) f[u]=v, size[v]+=size[u];//按大小合并每次要更新大小
        else f[v]=u, size[u]+=size[v];
    }
}
void unionn(int x, int y)
{//按深度合并//启发式合并
    int u=Get(x), v=Get(y);
    if(u != v) {
        if(high[u] < high[v]) f[u] = v;
        else {
            f[v]=u;
            if(high[u]==high[v]) high[u]++;//按深度合并只有在两树高度相等的时候更新
        }
    }
}

三、作用
操作1:统计当前产生的集合数目

for(int i=1;i<=n;i++)
{
	if(f[i]==i)
		cnt++;
}
因为初始化时f[i]=i,每个集合的树根节点会保留f[i]=i,统计集合个数其实就是在统计root个数

操作2:判断是否成环

简单说就是先把每一个顶点放在一个独立的集合(树)里,如果顶点之间是邻接的那么就把他们合并为一个集合(树)。一个集合(树)里有一个根结点,如果有两个顶点他们的根结点相同说明他们处于同一个集合(树),那这两个结点邻接必定形成一个环(为什么? 因n个顶点和n-1条边形成的连通图如果再加一条边一定出现环)。如果他们的根结点不同,就把这两个集合合成一个集合。

…有待补充

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值