1. 程式人生 > >算法導論——用於不相交集合的數據結構

算法導論——用於不相交集合的數據結構

inf 操作 每次 就是 alt ++ 一個 col 路徑

不相交集合的操作

一些應用涉及將n個不同元素分成一組不相交的集合,常進行兩種操作:尋找包含制定元素的唯一集合以及合並兩個集合。操作進行以下定於:

MAKE-SET(x)建立一個新的集合,僅含有x

UNION(x,y)將包含x和y的兩個集合合並成一個新的集合,刪除原本的集合

FIND-SET(x)返回一個指向包含唯一x的集合的指針

無向圖的連通分量就是一個例子。

技術分享圖片

對於如圖所示的4個連通分量,先對每一個單獨的點建立一個單獨的集合,然後依次根據每條邊合並對應的集合,最後形成4個不相交的集合

技術分享圖片

1 CONNECTED-COMPONENTS(E,V){//有E[n]個頂點V[m]條邊
2 for(i=0;i<n;i++) 3 MAKE-SET(V[i]); 4 for(i=0;i<m;i++){ 5 if(FIND-SET(V[i].u != FIND-SET(V[i].v)) 6 UNION(V[i].u,V[i].v); 7 } 8 }

不相交集合的鏈表表示

技術分享圖片

(a)所示的結構通過不相交集合各自形成一個鏈表,索引頭部包含鏈表的頭部和尾部,鏈表各個結點包含指向索引頭部和下個結點兩個指針。對於這種結構,MAKE-SET(x)和FIND-SET(x)都可以在O(1)的時間完成。

(b)展示了UNION(x,y)的操作,需要將另一個鏈表連接到一個鏈表的末尾,然後修改索引結點的尾部,同時被合並的鏈表每個結點指向的索引頭部都要修改,所以該操作至少要花費O(Y)的時間

為了減少合並的時間,可以在頭部額外存儲每個鏈表的大小,這樣可以將小的集合合並到大的集合中去。

不相交集合森林

使用有根樹來表示集合,書中每個節點包含一個成員,一棵樹代表一個集合,每個成員都指向他的父結點,根結點的父結點指向自己。

技術分享圖片

(b)是合並操作,將c的父親改為f即可。這種不相交集合森林的結構MAKE-SET和UNION的效率很高,但FIND-SET收到樹高度的影響,效率較低。因此,有兩種改進的啟發式算法。

第一種是按秩合並,對於每個結點記錄他的高度,將秩較小的結點的父親改為大的那個。若兩邊相等,則任選一個作為父親,根結點的秩加一。

第二種是路徑壓縮,每次調用FIND-SET的時候,將查找路徑上的結點的父親直接改為根結點。

技術分享圖片

 1 MAKE-SET(x){
 2     x.p = x;
 3     x.rank = 0;
 4 }
 5 
 6 UNION(x,y){
 7     if(x.rank > y.rank)
 8         y.p = x;
 9     else{
10         x.p = y;
11         if(x.rank == y.rank)
12             y.rank++;
13     }
14 }
15 
16 FIND-SET(x){
17     if(x != x.p)
18         x.p = FIND-SET(x,p);
19     return x.p;
20 }

算法導論——用於不相交集合的數據結構