并查集

并查集是一种树型的数据结构,用于处理一些不相交集合(Disjoint Sets)的合并及查询问题。常常在使用中以森林来表示。

主要操作

需要注意的是,一开始我们假设元素都是分别属于一个独立的集合里的。

合并两个不相交集合

操作很简单:先设置一个数组Father[x],表示x的“父亲”的编号。 那么,合并两个不相交集合的方法就是,找到其中一个集合最父亲的父亲(也就是最久远的祖先),将另外一个集合的最久远的祖先的父亲指向它。

void Union(int x,int y)
{    
	fx = getfather(x);    
	fy = getfather(y);    
	if(fy!=fx)       
		father[fx]=fy;
}

 判断两个元素是否属于同一集合

仍然使用上面的数组。则本操作即可转换为寻找两个元素的最久远祖先是否相同。可以采用递归实现。

bool same(int x,int y){   
	return getfather(x)==getfather(y);
}/*返回true 表示相同根结点,返回false不相同*/

并查集的优化

路径压缩

刚才我们说过,寻找祖先时采用递归,但是一旦元素一多起来,或退化成一条链,每次GetFather都将会使用O(n)的复杂度,这显然不是我们想要的。对此,我们必须要进行路径压缩,即我们找到最久远的祖先时“顺便”把它的子孙直接连接到它上面。这就是路径压缩了。使用路径压缩的代码如下,时间复杂度基本可以认为是常数的。

int getfather(int v)
{    
	if(father[v] == v)        
		return v;    
	else    
	{        
		father[v] = getfather(father[v]); /*路径压缩*/        
		return father[v];    
	}
}

Rank合并

合并时将元素少的集合合并到元素多的集合中。

void judge(int x ,int y) 
{     
	fx = getfather(x);     
	fy = getfather(y);      
	if (rank[fx]>rank[fy])        
		father[fy] = fx;     
	else     
	{        
		father[fx] = fy;        
		if(rank[fx]==rank[fy])           
			inc(rank[fy]);     
	}
}
/*Rank初始化*/
memset(rank,0,sizeof(rank));

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值