1. 程式人生 > >數據結構——並查集

數據結構——並查集

技術 bool 數組 用戶 span pen main 就是 set

並查集,是我目前為止見過的,實現起來最淳樸的數據結構,但是功能也很強大。

並查集核心由三個數組兩個函數構成。

數組pre[ ]記錄了每個點的前導點是什麽,數組data[ ]記錄數據,數組size[ ]記錄每個點包含節點(自己和所有下級節點)的個數。

函數find是查找某個節點,返回該節點的最終前導;

函數union是將給的兩個節點所在的集合 合並。

對於查找操作,假設需要確定x所在的的集合,也就是確定集合的代表元。可以沿著pre[x]不斷在樹形結構中向上移動,直到到達根節點。為了加快查找速度,在查找過程中可以實現路徑壓縮:

//查找
int Find(int x) {
    if
(pre[x] == x)return x; //用哪一個在於是否需要壓縮路徑 //return pre[x] = Find(pre[x]); return Find(pre[x]); }

技術分享圖片

這是並查集的合並,實際運用中具體合並方法還是要看題目的。

//合並
void Union(int x, int y) {
    int fx = Find(x), fy = Find(y);
    if (fx == fy) return;
    //fx的深度大於fy的話,把fy掛上去,不會增加rank
    if (rank[fx] > rank[fy]) 
        pre[fy] 
= fx; else { if (rank[fx] == rank[fy])rank[fy] ++; pre[fx] = fy; } }

完成實現代碼:

技術分享圖片
int pre[1000];
int data[1000];
int rank[1000];


//對n個節點進行初始化
void init(int *a, int n) {
    for (int i = 0; i < n; i++) {
        //這裏接收用戶輸入時直接輸入進來更好
        data[i] = a[i];
        pre[i] = i;
        rank[i] 
= 1; } } //查找 int Find(int x) { if (pre[x] == x)return x; return pre[x] = Find(pre[x]); } //合並 void Union(int x, int y) { int fx = Find(x), fy = Find(y); if (fx == fy) return; //fx的深度大於fy的話,把fy掛上去,不會增加rank if (rank[fx] > rank[fy]) pre[fy] = fx; else { if (rank[fx] == rank[fy])rank[fy] ++; pre[fx] = fy; } } //判斷兩個結點,是否位於同一集合 bool IsSameSet(int x, int y) { return Find(x) == Find(y); }
View Code

OJ練習:


HDU 1232 :http://acm.hdu.edu.cn/showproblem.php?pid=1232

技術分享圖片技術分享圖片

基本思想是:N個節點,最少需要N-1根線連起來。

把輸入的城鎮全部進行Union,如果這兩個城鎮不連通,N--,最後輸出N-1就是答案,其實比上面實現的並查集結構更簡單,只需要一個Pre數組就可以了。

#include<stdio.h>

int Pre[1001];

//查找
int Find(int x) {
    if (Pre[x] == x)return x;
    return Pre[x] = Find(Pre[x]);
}
//合並
void Union(int x, int y, int &n) {
    int fx = Find(x), fy = Find(y);
    if (fx == fy) return;
    Pre[fx] = fy;
    n--;
}

int main() {
    int n, m;
    while (~scanf("%d", &n)) {
        if (n == 0) break;
            //這裏註意不要寫成i<n了,-_-
        for (int i = 0; i <= n; i++) Pre[i] = i;
        scanf("%d", &m);
        while (m--) {
            int c1, c2;
            scanf("%d%d", &c1, &c2);
            Union(c1, c2, n);
        }
        printf("%d\n", n - 1);
    }
    return 0;
}    

HDU 1879 :http://acm.hdu.edu.cn/showproblem.php?pid=1879

數據結構——並查集