數據結構與算法-並查集

並查集(Disjoint set或者Union-find set)是一種樹型的數據結構,常用於處理一些不相交集合(Disjoint Sets)的合併及查詢問題。

基本操作

並查集是一種非常簡單的數據結構,它主要涉及兩個基本操作,分別為:

A. 合併兩個不相交集合

先設置一個數組Father[x],表示x的“父親”的編號。 那麼,合併兩個不相交集合的方法就是,找到其中一個集合最父親的父親(也就是最久遠的祖先),將另外一個集合的最久遠的祖先的父親指向它。

C語言代碼如下:

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

B. 判斷兩個元素是否屬於同一個集合

尋找兩個元素的最久遠祖先是否相同。尋找祖先可以採用遞歸實現。

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

並查集的優化

A 路徑壓縮

尋找祖先時採用遞歸,但是一旦元素一多起來,或退化成一條鏈,每次GetFather都將會使用O(n)的複雜度,這顯然不是我們想要的。

對此,我們必須要進行路徑壓縮,即我們找到最久遠的祖先時“順便”把它的子孫直接連接到它上面。這就是路徑壓縮。

C語言代碼如下:

int getfather(int v)
{
if (father[v] != v)
{
father[v]=getfather(father[v]);//路徑壓縮
}

return father[v];
}

Rank合併

合併時將元素所在深度小的集合合併到元素所在深度大的集合。

void Union(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])
++rank[fy]; ////若兩樹一樣高,那麼合併後,高度加一
}
}

應用

對並查集而言,一個簡單的應用就是判斷無向圖的連通分量個數,或者判斷無向圖中任何兩個頂點是否連通。


分享到:


相關文章: