优化并查集

对并查集来说,可能正常情况下会退化为链表,就是树太高了,那我们如何改变呢,那就用路径压缩了,以下用两种路径压缩的方法。
原来的未路径压缩

int find(int x){
	int s=x;
	while(pre[s]!=s){
		s=pre[s];       //当s不是根节点,指向它的父节点 
	}
	return s; 
}

接下来提供两个路径压缩方法,当然会有缺陷,就是会破坏rank,但你可以不用管它,根据对比和概率来说,继续保留rank会更好,虽然rank被破坏,但在随机性上来说,还是保留更好。
简单的路径压缩

int find(x){
	int s=x;
	while(pre[s]!=s){
		pre[s]=pre[pre[s]];    //该节点指向其爷爷节点,若父亲节点是根节点,该式子也成立
		s=pre[s];              //跳到他的新父亲节点 
	}
	return s;
}

下面写出基于递归的优秀路径压缩

int find(x){
	int p=x;
	if(p==pre[p]){
	return p;	//此时根节点为p		    
	}
	else{
	pre[p]=find(pre[p]);    //一直递归 找到祖先
	return pre[p];          //实际上 ,所有的pre[x]=祖先 
	}
}

上式要理解一下,假设有一条链a->b->c->d>e;
开始pre[a]=b,pre[b]=c,pre[c]=d,pre[d]=e,pre[e]=e;
然后一直执行pre[s]=find(pre[s]);
直到
if(p==pre[p]){
return p; //此时根节点为p
}
然后一直执行return pre[s];会发现pre[s]不断改变为e返回e。

发布了6 篇原创文章 · 获赞 8 · 访问量 144

猜你喜欢

转载自blog.csdn.net/weixin_45981189/article/details/104876022
今日推荐