並查集是一種樹型的高階資料結構,主要用於處理不相交集合的合併及查詢問題。它在電腦科學中有著廣泛的應用,例如求解最小生成樹、親戚關係的判定、確定無向圖的連通子圖個數、最小公共祖先問題等,都要用到並查集。
集合是數學中最基本的構造之一,將一組滿足某種性質的物件放在一起就形成了集合。集合中包含的物件稱為集合中的元素,集合中的元素是無序而且唯一的。人們常用大寫英文本母a、b、c等來表示集合,並用x∈a來表示x是集合a中的元素。
由a、b集合的全體元素組成的集合為a與b的並集,記作aub;a與b的公共元素組成的集合稱a與b的交集,記作a∩b;屬於集合a而不屬於集合b的元素組成的集合稱為a減b的差,記作a-b。
由於集合中存放的是一組具有相同性質的物件,一般人很容易想到用陣列來儲存。用陣列很容易實現集合型別,但要注意:因為陣列一旦定義,其大小就固定不變。所以在定義的時候,要充分考慮最大空間。
也可以用鍊錶來儲存集合元素。鍊錶可以很容易的動態生成和釋放,所以增減節點是很方便的,完全不用考慮象陣列那樣的長度問題。刪除元素也很方便。但是因為涉及到指標,實現起來很容易出錯。
還可以用vector.它有陣列的優點,而且又不必考慮陣列那樣可能越界的情況。
在某些應用中,我們要檢查兩個元素是否屬於同乙個集合,或者將兩個不同的集合合併為乙個集合。這是不相交集合經常處理的兩種操作:查詢和合併,我們稱為並查集。
並查集共有兩個函式,root和union。
查詢root:查詢乙個指定元素屬於哪個集合.
合併union:將兩個集合合併為1個集合。
除了這兩個操作之外,還有乙個基礎的操作——makeset,用於建立只有1個元素的集合。
為了更精確的定義上述三個操作,我們需要用一種方法來表示集合。一種通用的做法是選擇集合中某個固定的元素作為集合的代表,即該元素作為整個集合的唯一標識。一般說來,選取的代表是任意的。也就是說,到底選取集合中的哪個元素作為它的代表是無關緊要的。
在並查集中,我們對於集合的表示利用樹的結構,乙個集合表示為一棵樹,樹根即代表該集合的標識。如果兩個元素在同乙個樹中,則它們是同乙個集合;合併兩個集合,即是對兩棵樹進行合併。
root(x):返回元素x所屬集合的代表。為了判斷任意兩個元素x和y是否屬於同乙個集合,我們只需要判斷root(x)和root(y)是否相等即可,如果相等,說明他們屬於同乙個集合,否則他們不屬於同乙個集合。
union(x,y):將包含元素x的集合(假設為sx)和包含元素y的集合(假設為sy)合併為乙個新的集合(即這兩個集合的並集),所得到並集可以用它的任何乙個元素來做代表,一般我們都原來的某棵樹的根作為合成的新樹的根。
makeset(x):建立乙個只包含元素x的集合,顯然,此時該集合的代表應該而且只能為x.
void makeset(x)
parent[x]表示x的父親編號.
最開始的,每個元素自成乙個集合,即每個元素開始都當做一棵樹,其父親節點初始為-1,表示它沒有父親。
int root(x)//查詢x所在的集合。
void myunion(int x,int y)
這是路徑壓縮。它可以在find的過程中,讓路徑上的元素都成為根的兒子節點。這樣,從形式上看,樹就從細長型變成了扁平型。
使用路徑壓縮技術後,合併時不需要再使用height陣列來判斷兩棵樹誰高誰低了。親戚
犯罪團夥
食物鏈無所不在的宗教
改寫kruscal演算法
kruscal演算法求最小生成樹。
演算法框架:
將所有邊按小到大排序。
依次選取邊,如果當前的邊和之前選擇的邊不會形成環路,則選取當前邊;若果形成環路,則不選擇當前邊。
迴圈執行2,直到選取的邊的數目達到n-1條為止。
如何判斷當前選擇的邊是否會和之前選擇的邊形成環路?
若當前選擇的邊的兩個頂點為a,b,若a,b已經聯通,則當前邊必然導致迴路;繁殖,若a,b本不連通,則當前邊必然不會導致迴路。
我們將聯通的點作為乙個集合,用並查集可以在logn時間內判斷某兩個點是否乙個集合,也可以在logn時間內合併兩個集合。
並查集詳解
其實並查集顧名思義就是有 合併集合 和 查詢集合 兩種操作的關於資料結構的一種演算法。並查集演算法不支援分割乙個集合。用集合中的某個元素來代表這個集合,該元素稱為集合的代表元。乙個集合內的所有元素組織成以代表元為根的樹形結構。對於每乙個元素 parent x 指向x在樹形結構上的父親節點。如果x是根...
詳解並查集
並查集主要用來求解不相交集合的問題,主要針對於合併和查詢兩種演算法。並查集的實現主要包含了三個部分 並查集的初始化是對單個資料建立了乙個單獨的集合,每個集合應該包含以下兩個資料 由以上兩個資料,一般的並查集的結構一般有兩種表示形式 結構體構造如下 define max 50 struct node ...
並查集詳解
看大佬的形象解釋 並查集 按我現在對這個的理解 就是給你一堆數,然後給你兩個兩個數的關係,然後關係的傳遞性 連帶性 這些數就都有了關係 有關係的數組成乙個陣列,然後輸出這個一維陣列,裡面有幾個沒關係的陣列 應該怎麼做呢?第一種解釋是 每給兩個數就把乙個數當成祖宗,把另乙個數當成孩子,然後給了孩子和另...