不相交集及應用

2021-06-16 13:04:18 字數 2361 閱讀 2788

乙個集合s,集合中乙個元素a。a的等價類是s的乙個子集,該子集包含所有與a有關係的元素。

等價類形成是對s的乙個劃分且s中的每乙個成員恰好出現在乙個等價類中。這樣,判斷a與b是否有關係,

只需要判斷a與b是否在乙個等價類中即可。

對於集合s劃分,取任意兩個等價類,si與sj,如果si∩sj = ∅,則稱這些集合不相交。

對於不相交集,有兩種操作,union/find操作。find操作找包含給定元素的集合(等價類)名字。

union把兩個等價類合併成乙個新的等價類。

資料結構:採用樹來表示每乙個集合(等價類),因為樹上的元素都有乙個共同的根。

union(x, y),將x,y合併成乙個新的等價類,且x做為根。

這樣的構造方法,最壞情況下可以構建一課高度為n-1的樹,即union(7,8), union(6,7), union(5,6)……

這使得find操作在n-1次操作下才能找到樹根,執行時間o(n)

將上述森林用陣列表示,約定陣列1-8個元素對應的值代表其父親,例如元素8對應的值為7,表示其父親為7。

而5對應的值為0,表示5本身就是樹根。

這樣找樹根就是乙個遞迴過程,如:find(8), 父親為7, 執行find(7),父親為5,執行find(5),對應值為0,表示5為樹根,遞迴結束,

這樣即找到8所在等價類的樹根為5。判斷6,8是否有關係,即find(8) == find(6)是否成立。

typedef int settype;

typedef int elementtype;

typedef int* disjset;

disjset initialize(int num)

void destroy(disjset s)

void union(disjset s, settype root1, settype root2)

settype find(disjset s, elementtype x)

int main()

為了避免樹的深度過大,可以每次讓深度大的樹做為新根,這樣減少樹深度增加速率。

那麼就需要記住當前根的深度,而由於我們只採用了乙個陣列,所以,可以讓根的值為負值,代表深度。

這樣,根節點的值為-1,表示深度為-1。

對於上述情形,執行union(4,5)。按照之前的union操作,得到結果為:

優化後結果

對應優化後結果的陣列如下:

}對於比較深的樹,find操作還是比較耗時的,要一步一步遞迴直至樹根。

執行一次find(8)操作。由於元素8所在樹的樹根為5,所以執行find後,陣列要變成。

這樣,當進行下一次呼叫find(8)的時候,能夠快速找到8對應的樹根。

settype find(disjset s, elementtype x)

不相交集應用 kruskal演算法

問題描述 已知含有n個頂點的帶權連通無向圖,採用鄰接矩陣儲存,鄰接矩陣以三元組的形式給出,只給出不包括主對角線元素在內的下三角形部分的元素,且不包括不相鄰的頂點對。分別採用prim演算法和kruskal演算法,求該連通圖的最小生成樹的權值之和。輸入形式 第一行給出結點個數n和三元組的個數count,...

不相交集ADT

1.不相交集是解決等價關係的一種資料結構,執行合併和查詢的速度都非常快,m次執行合併和查詢的執行時間為 m logn 在乙個集合中,對於每一對元素 a,b a,b s,對於關係r如果滿足下面三個條件,則成關係r為等價關係 1 自反性 對於所有a s,ara 2 對稱性 arb當且僅當bra 3 傳遞...

不相交集ADT

首先我們必須明白不相交集這種資料結構是用來幹什麼的。不相交即主要用來實現動態等價問題的求解。動態 等價問題 這裡不再說明等價關係的概念,這個可以參考數理邏輯之類的書。假設我們有乙個集合和乙個等價關係 針對集合中的任意兩個元素 a 和 b,我們如何確定他們有等價關係 即a b.那麼我們需要等價類的概念...