優化並查集

對並查集來說,可能正常情況下會退化爲鏈表,就是樹太高了,那我們如何改變呢,那就用路徑壓縮了,以下用兩種路徑壓縮的方法。
原來的未路徑壓縮

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。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章