資料結構 並查集 路徑壓縮

2021-07-04 05:28:10 字數 1187 閱讀 9998

經常會遇到對於給定的n個點,求出他們能否相互連通的問題,常規的做法可能是用二維陣列進行標記處理,但是這樣的空間使用是o(n^2),當資料量很大的時候,這個消耗是很恐怖的,所以這裡我們引入並查集的這種資料結構。

樹是一種資料結構,它的特點在於所有的點有且僅有乙個根節點,如果我們能構造一棵樹,並把所有的樹按照相互關係裝入這棵樹,那麼他們就是屬於乙個集合,他們都互相連通的。

我們可以用陣列來構建這樣乙個模型。

int

parent[n];

用這樣乙個陣列,記錄每個點屬於哪個集合,最初所有的點都是孤立的。所以等於它本身。

每次我們都需要查詢他們所屬的集合,是否為同乙個集合,如果不是,就可以把它們連通。

而且我們可以建立簡單的樹形關係:

這樣查詢的次數為層數。

注意有一種最壞的情況,就是如同鍊錶那樣,查詢次數就接近總數的一半了。

int findx(int x)

這裡我們給出乙個很簡單的查詢方法,首先用變數r儲存需要查詢的值,然後每次查詢r的父節點,儲存它的父節點,查詢它父節點的父節點……最後就能找到答案。

但我們想想,對於每個數,我們每次都需要去查詢它根節點的時候都要很多時間,而且我們真實需要的並不是它的父節點的值,而是它根節點的值。

如果我們能構建如下的樹:

這樣查詢的效率就是o(1),因為只有一層,所以我們查詢的時間很少,這裡就用到了路徑壓縮,我們先看壓縮過的**:

int findx(int x)       

return

parent[x];

}

這樣我們每次都會去更新父節點的值變成根節點的值。

但是用遞迴會出現一種問題,爆堆疊。

windows對堆疊的限制很大,所以我們可以放棄遞迴,用遞推式。

int findx(int x)

return r;

}

這種非遞迴方式更安全。

路徑壓縮 並查集路徑壓縮

如何描述乙個複雜的連線關係?如圖,很容易判斷緊鄰的2個人關係,但中間的連線很多很亂,怎麼判斷出兩個人的關係呢?並查集就是一種結構,通過儲存節點以及節點上的標籤,來判斷這兩個節點是否連線在一起。當兩個節點繫結時,可以任選其中乙個節點的標籤,指定另乙個節點。當判斷兩個節點是不是連線時,可以上溯節點的祖宗...

並查集 壓縮路徑

並查集 union findsets 一種簡單的用途廣泛的集合.並查集是若干個不相交集合,能夠實現較快的合併和判斷元素所在集合的操作,應用很多,如其求無向圖的連通分量個數等。最完美的應用當屬 實現kruskar演算法求最小生成樹。並查集的精髓 即它的三種操作,結合實現 模板進行理解 1 make s...

並查集路徑壓縮

使用並查集查詢時,如果查詢次數很多,那麼使用樸素版的查詢方式肯定要超時。比如,有一百萬個元素,每次都從第一百萬個開始找,這樣一次運算就是10 6,如果程式要求查詢個一千萬次,這樣下來就是10 13,肯定要出問題的。這是樸素查詢的 適合資料量不大的情況 int findx int x 下面是採用路徑壓...