算法學習->並查集

一、什麼是並查集

並查集,在一些有N個元素的集合應用問題中,我們通常是在開始時讓每個元素構成一個單元素的集合,然後按一定順序將屬於同一組的元素所在的集合合併,其間要反覆查找一個元素在哪個集合中。
並查集是一種樹型的數據結構,用於處理一些不相交集合(Disjoint Sets)的合併及查詢問題。常常在使用中以森林來表示。

二、並查集的基本操作

1、初始化

把每個點所在集合初始化爲其自身。
通常來說,這個步驟在每次使用該數據結構時只需要執行一次,無論何種實現方式,時間複雜度均爲O(N)。模板代碼如下:

int fa[110];

void Init(){
    for(int i=0;i<maxn;i++){
        fa[i]=i;
    }
} 

2、查找

查找元素所在的集合,即查找根節點。模板代碼如下:

int find(int x){
    return x==fa[x]?x:fa[x]=find(fa[x]);    //路徑壓縮 
} 

在這裏路徑壓縮是爲了優化時間,該操作就是將一個集合直接合併到另一個集合的根節點上,形成類似只有葉子結點的樹一樣,當去查找集合中的一個元素時,遞歸查找的次數會變少。

3、合併

將兩個元素所在的集合合併爲一個集合。
通常來說,合併之前,應先判斷兩個元素是否屬於同一集合,這可用上面的“查找”操作實現。
模板代碼如下:

void merge(int x,int y){
    int a=find(x);
    int b=find(y);
    if(a!=b){
        fa[a]=b;    //將a元素的父節點設爲b 
    }
} 

另外,其實還可以改進merge,把元素數量少的集合合併到數量大的集合中,不過這就要記錄每個集合中的元素數量,相當於增加了O(N)的存儲空間(空間換時間),而且在find中也應該保持對元素數量的維護,相對代碼複雜度偏高,而且感覺性能提升不多,初學者可以先不掌握。

三、並查集的應用

1、凡是涉及到兩個站點通信或是否連通的問題,可以考慮並查集操作。
2、凡是涉及到兩個島國是否有通路的問題,可以考慮並查集操作。
3、凡是涉及兩個事物是否有什麼關係的問題,例如,兩個人之間的關係,可以考慮並查集操作。
總的來說,就是凡是有關連通和關係的問題,可以考慮並查集。

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