并查集操作

并查集用来管理元素分组情况的数据结构。

1.初始化集合。数组fa记录每个节点的父节点编号,初始时各元素单独形成一个集合,fa[x]=x,x是所在树的根。另设rank数组记录根节点的秩,可以是树高度,也可以是集合内元素个数。

void init(int n)
{
	for(int i=0;i<n;i++)
	{
		fa[i]=i;
		rank[i]=1;
	}
 } 
 

2.查找元素所属集合。沿着树向上走,找到该树的根元素。为了避免出现退化,这里采用路径压缩的优化方法,将查询过程中向上经过的所有节点都改为直接连到根节点上,这样在之后查询这些节点时可以很快找到根节点。

int find(int x)
{
	if(fa[x]!=x)
		fa[x]=find(fa[x]);
	return fa[x];
}
//非递归方法
int find(int x)
{
	int r = x;		
	while (fa[r] != r)	//查找根节点r
		r = fa[r];
	int y;
	while (x != r)		//路径压缩算法
	{
		y = fa[x];	//记录x当前父节点
		fa[x] = r;	//将根节点设为x父节点
		x = y;		
	}
	return r;
}

3.合并集合。先找出x,y各自所属集合的根节点,若不属于一个集合则进行合并,将一个组的根连向另一个组的根。可采用启发式合并的优化:根据根节点rank[]记录的秩,将rank小的根向rank大的根连边。

void unite(int x,int y)
{
	x=find(x),y=find(y);//各自根节点 
	if(x==y) return;
	if(rank[x]>rank[y])
		fa[y]=x;
	else
	{
		fa[x]=y;
		if(rank[x]==rank[y]) rank[y]++;//高度+1
	} 
}

判断是否属于同一集合:

bool same(int x,int y)
{
	return find(x)==find(y);
}

并查集平均复杂度为O(α(n))。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值