乙個集合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)是否成立。
1 typedef intview codesettype;
2 typedef int
elementtype;
3 typedef int*disjset;
45 disjset initialize(int
num) 6
1314
void
destroy(disjset s)
15
1819
void
union(disjset s, settype root1, settype root2)
20
2324
settype find(disjset s, elementtype x)
25
3132
intmain()
33
為了避免樹的深度過大,可以每次讓深度大的樹做為新根,這樣減少樹深度增加速率。
那麼就需要記住當前根的深度,而由於我們只採用了乙個陣列,所以,可以讓根的值為負值,代表深度。
這樣,根節點的值為-1,表示深度為-1。
對於上述情形,執行union(4,5)。按照之前的union操作,得到結果為:
優化後結果
對應優化後結果的陣列如下:
對於比較深的樹,find操作還是比較耗時的,要一步一步遞迴直至樹根。
改進思路:執行一次find後,讓該路徑上,所有節點直接指向根,而不需要指向父親,這樣下一次查詢的時候能夠快速找到根,節約時間。
執行一次find(8)操作。由於元素8所在樹的樹根為5,所以執行find後,陣列要變成。
這樣,當進行下一次呼叫find(8)的時候,能夠快速找到8對應的樹根。
1view codesettype find(disjset s, elementtype x)
2
**:
《資料結構與演算法分析》不相交集
前言 回來到學校,今天又要開始苦逼的工作了,後悔回家玩去了,現在想學習時間又不夠了。就是這麼傻 我的github 不相交集 思想 不相交集是解決等價問題的一種有效的資料結構,之所以稱之為有效是因為,這個資料結構簡單 幾行 乙個簡單陣列就可以搞定 快速 每個操作基本上可以在常數平均時間內搞定 首先我們...
資料結構與演算法分析 不相交集類
不相交集類是解決等價問題的一種有效資料結構,實現簡單,很少,速度快。等價關係 對於任意一對元素a,b s,定義關係 使得a b要麼為true要麼為false 1.自反性 對於所有的a s,a a 2.對稱性 a b當且僅當b a 3.傳遞性 若a b且b c則a c 等價類 對於元素a s,等價類是...
資料結構 不相交集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屬...