不相交集合維護了乙個不相交動態集的集合,選用乙個代表元素來標識每個集合,並不關心哪個元素作為代表(當然,還是有一定的選取規則)。
每個集合都有自己的乙個鍊錶。每個集合包含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...