並查集 Union Find Set 的學習

2022-06-08 12:18:13 字數 1679 閱讀 1365

什麼是並查集?

乙個實現了合併與查詢集合的資料結構。可以解決動態連通性一類的問題。

那什麼是動態連通性問題?

給出一系列的物件時,讓其支援下列操作:

這裡以整數表示物件,有0-9共十個整數,當給出乙個整數對(a,b)時表示將整數a和b相連(如果a、b不相連),如下圖所示:

隨著整數對的輸入,十個整數的連通性會發生變化,這就是動態連通性問題

在動態連通性問題中,我們假設「相連」是一種等價關係,也就意味著他具有:

在所有給出的物件中,所有相連的一組物件稱為連通分量(connected component),如上圖最後一行的(0,1,2,5,6,7)和(3,4,8,9)發別為兩個連通分量。

應用

設計演算法

動態連通性問題要求給出的兩個點是否相連,並不要求給出具體的連線路經;至於得出連線路經的問題,可以通過深度優先搜尋(dfs)演算法來解決。

在union-find演算法中,要實現如何操作:

對應api如下:

**實現

既然用分量識別符號代表乙個分量,那麼直接使同一分量中的所有觸點的分量識別符號相同即可,在判斷兩個觸點的連通情況時只需判斷其分量識別符號是否相同,即id[q]==id[p]。那麼在實現union()方法時,首先判斷q,p是否屬於同一分量,如果不是,則需要合併兩者所代表的分量。根據同一分量中所有觸點的分量識別符號相同的原則,遍歷整個陣列,將所有與id[p]相等的元素值變為id[q]。這樣的實現稱為quick-find(快速查詢)演算法。此演算法的時間複雜度為平方級別的,當陣列較大時,執行效率就較低。

在quick-find演算法中,find()的速度是很快,而union()操作在需要合併分量時要遍歷整個陣列而效率較低。在合併分量時,需要關注的並不是所有的觸點,只是與元素p同屬乙個分量的觸點才需被訪問,因此,將同一分量的觸點組織結合起來,當需要修改時直接訪問該分量中的觸點可以減少無關觸點的訪問。

同樣是以觸點為索引的id組數,但其中儲存的值不再是相同的分量識別符號,而是同乙個分量中另乙個觸點(可能是自已)的名稱。而實現find()方法時,從給定的觸點開始,再同這個觸點鏈結到第三個觸點,直到根觸點--鏈結指向自已的觸點,那麼這個根觸點就代表了這個分量。當判斷兩個觸點是否相連時,沿著各自的鏈結得到根觸點後比較根觸點是否相同即可。

在實現union()方法時,為了能保證合併後兩個分量的所有觸點的根觸點相同,直接到其中乙個分量的根觸點鏈結到另乙個分量的根觸點上就可以快速的合併兩個分量。因為這個演算法稱為quick-union(快速合併)演算法

從上圖的示意圖可以看出,quick-union演算法是採用樹結構來採代quick-find演算法中使用的陣列來來組織元素,實現高效的查詢與修改。

leetcode相關題目

684. redundant connection

547737

並查集 Union Find Set 小結

做了幾道並查集的題,在這裡做乙個小小的總結,以表達我對這個精簡的資料結構的淺顯的理解。先說說用途 1 並查集,顧名思義分為並和查。並 即 將兩個完全不相交的集合合併為乙個集合。查 查詢某個元素屬於哪乙個集合,一般用來判斷兩個元素是否屬於同一集合。2 目前我所接觸到的它的實際用途 1 求解最小生成樹 ...

一 並查集 Union Find Set)

如果 給出各個元素之間的聯絡,要求將這些元素分成幾個集合,每個集合中的元素直接或間接有聯絡。在這類問題中主要涉及的是對集合的合併和查詢,因此將這種集合稱為並查集。鍊錶被普通用來計算並查集.表中的每個元素設兩個指標 乙個指向同一集合中的下乙個元素 另乙個指向表首元素。鏈結構的並查集 採用鏈式儲存結構,...

並查集 並查集

本文參考了 挑戰程式設計競賽 和jennica的github題解 陣列版 int parent max n int rank max n void init int n int find int x else void union int x,int y else 結構體版 struct node ...