并查集

1,首先并查集,从名字我们就可以出来,这个一个可以完成合并和查询操作的集合。

2,并查集,假设你有N个元素,且每个元素形成了一个集合。然后我们根据某种规律将这些元素合并成一些大些的(可能)集合,其间我们要反复查询某些元素是否在某个集合中。

3,具体来说,并查集是一种树形结构,用来处理不相交集合的合并与查询问题。比如你可以用它来进行无权值有向图中的求最小环问题。

4,可以借用武侠那个例子;  

//路径压缩的循环条件有问题。

    假设武林有3000多武林人士,用数组int fa[3000],记录每位大侠的老大。

    ①,打架前为了找各自的老大,我们需要find操作。

int find(int x)
{
	int r=x;//这里有个委托的思想,其实也就是函数传参的那点破事 
	while(fa[r]!=r)
	{
		r=fa[r];
		
	 } 
	 return r;
	
} 

  

    ②,分久必合。大家最终形成了3个门派,武当,少林,朝廷。

     那么这就涉及到了合并操作,很简单直接连就可以了。

void merge(int x,int y)
{
	int r1,r2;//注意这里的传参思想
	r1=fa(x);
	r2=fa(y);
	if(r1!=r2)
	{
		fa(y)=x;//注意这里直接用的是x和y; 
	}
}

 5,

但是大家发现这个merge函数中谁当掌门竟然在我的操作下完全是随机的,完全不符合“上天无德,维德是辅”传统思想。于是为了平复这群人的怨气,我决定改进一下merge 函数。即路径压缩算法。

换一个角度,不是说了是树形结构了嘛?所以也就是尽量维持树的层数在一个较低的层数上。

6,上面的意思大致是对的,但是操作在find函数中,这是更改后的find函数。

int find(int x)
{
	int r=x;//这里有个委托的思想,其实也就是函数传参的那点破事 
	while(fa[r]!=r)
	{
		r=fa[r];
		
	} 
	 while(r!=x)
	{
		int tmp=fa[x];//其实吧还是挺好想的 ,另外有图片可以帮你理解。 
		fa[x]=r;
		x=tmp;
	 	
	}
	 return r;

 恩,我还画了个简单的图来帮你理解

7,这个图啊。。我不像说什么了

不过我感觉你画的挺好,教的似乎也蛮不错的,但是

我基本都忘了哈哈。。

给你在路径压缩的基础上再来一个优化就是每次把矮的树连到高的树上。

换句话说就是记录集合的大小,小集合往大集合上靠。

虽然我他妈妈已经忘光了

啥啥启发式合并?》》

玄学啊。

原文地址:https://www.cnblogs.com/beiyueya/p/11709748.html