不相交集合的資料結構和操作

2021-10-23 18:21:50 字數 1371 閱讀 7135

不相交集合維護了乙個不相交動態集的集合,選用乙個代表元素來標識每個集合,並不關心哪個元素作為代表(當然,還是有一定的選取規則)。

每個集合都有自己的乙個鍊錶。每個集合包含head和tail屬性,head指向第乙個物件,tail指向最後乙個物件。鍊錶的每個物件都有乙個集合成員(也就是本身),乙個指向下乙個物件的指標,乙個回到集合物件的指標。代表是鍊錶中的第乙個物件。

鍊錶表示下make-set(x)和find-set(x)都是o(1)的複雜度,但union操作會隨著鍊錶的增長消耗大量時間。

改進方法是用一種所謂加權合併啟發式策略,在每個鍊錶上維護乙個長度變數,合併時總是把短的鍊錶合併到長鍊錶的後面,這樣union操作的時間成本會降低。

用樹來表示集合,每棵樹的根就是集合的代表,而且根是自己的父節點,每個成員僅指向自己的父節點。

在這種實現中,find-set(x)向上尋找父節點直到返回根,union(x,y)把一棵樹的根指向另一棵樹的根。

兩種改進執行時間的策略

按秩合併(union by rank)

類似鍊錶實現中的加權合併啟發式策略,把結點較少的樹的根指向結點多的樹根,這裡要維護乙個秩來表示乙個結點的上界。

路徑壓縮(path compression)

使查詢路徑上的所有結點直接指向根結點,且不改變結點的秩。

實現:對於每個結點 x

xx,維護有乙個整數值 x.r

an

kx.rank

x.rank

,代表從 x

xx 到某一後代葉子結點的最長簡單路徑上的邊的數目。

make-set(x)

x.parent = x

x.rank =

0

rank初始化為0,根節點的parent結點為本身。

union(x,y)

link(find-set(x),find-set(y))

link(x,y)

if x.rank > y.rank

y.parent = x

else x.parent = y

if x.rank = y.rank

y.rank +

=1

union的引數是任意的不在同一棵樹的兩個結點,link的引數是兩個結點對應的根節點。

link方法中,如果x的秩等於y的秩,任意選擇乙個並給新的根節點的秩加一。

find-

set(x)

if x != x.parent

x.parent = find-

set(x)

return x.parent

有路徑壓縮的find-set(x),會將x的搜尋路徑上所有的結點的父節點更新到根節點。

用於不相交集合的資料結構

make set x 建立乙個集合,它的唯一成員 因而為代表 是x。因為各個集合是不相交的,所以x不會出現在別的某個集合中 union x,y 將包含x和y的兩個集合合併。假定操作之前著兩個集合是不相交的。find set x 返回乙個指標,這個指標指向包含x的 唯一 集合的代表。按秩合併 秩表示該...

資料結構 不相交集ADT

若對於每一對元素 a,b a b屬於s,arb或者為true或者為false,則稱在集合s上定義關係r。如果arb是true,那麼我們說a與b有關係。等價關係是滿足下列三個性質的關係r 自反性 對於所有的a屬於s,ara 對稱性 arb當且僅當bra 傳遞性 若arb且brc,則arc 乙個元素a屬...

不相交集資料結構

用乙個1x3的陣列來儲存每個數的數 其父親 秩。首先尋找合併的兩個樹的根的根,然後按照秩的大小將兩個樹進行合併。尋找兩個數的根時,順便壓縮其與根的距離 include define max 100 int find int a 3 int n void rootunion int a 3 int m...