《資料結構與演算法分析》不相交集

2021-07-04 15:55:34 字數 3625 閱讀 4105

前言:

回來到學校,今天又要開始苦逼的工作了,後悔回家玩去了,現在想學習時間又不夠了。。。就是這麼傻

我的github:

不相交集:

思想:

不相交集是解決等價問題的一種有效的資料結構,之所以稱之為有效是因為,這個資料結構簡單(幾行**,乙個簡單陣列就可以搞定),快速(每個操作基本上可以在常數平均時間內搞定)。

首先我們要明白什麼叫做等價關係,而在這個之前要先有乙個關係(relation)的定義

relation:定義在資料集s上的關係r是指,對於屬於資料集s中的每一對元素(a,b),a r b要麼是真要麼是假。如果a r b為真,就說a related b,即a與b相關。

等價關係也是一種關係(relation),只不過是要滿足一些約束條件

a) a r a,對於所有屬於s的a

b) a r b 當且僅當 b r a

c) a r b 並且 b r a 意味著 a r c

動態等價性問題:

定義在非空集合s上的關係r,對於任意屬於資料集s中的每一對元素(a,b),確定a r b是否為真,也就是說a與b是否有關係。

而對於a與b是否有關係,我們只需要證明a與b是否在同乙個等價類集合中。

基本資料結構與操作:

find操作:返回給定元素的集合的名字,也就是檢查a,b是否在同乙個等價類中。對於find運算,最重要的是判斷find(a,s) == find(b,s)是否成立。

union操作:如果a,b不在乙個等價類中,可以用union操作把這連個等價類合併為乙個等價類。

我們可以用tree結構來表示乙個集合,root可以表示集合的名字。由於僅有上面的兩個操作而沒有順序資訊,因此我們可以將所有的元素用1-n編號,編號可以用hashing方法。

進一步可以發現對於這兩個操作無法使其同時達到最優,也就是說當find以常數最壞時間執行時,union操作會很慢,同理顛倒過來。因此就有了2種實現方式。

a)使find執行快

在陣列中儲存每個元素的等價類的名字,將所有等價類的元素放到乙個鍊錶中

b)使union執行快

使用樹來表示每乙個集合,根節點表示集合的名字。陣列元素p[i]表示元素i的父親,若i為root,則p[i]=0。

對於union操作,相當於把連個樹合併,也就是指標的移動,如下圖所示:

編碼實現:

對於實現這樣的資料結構,只需要使用陣列就可以完成,讓每乙個節點中儲存其父親節點的編號,然後根節點中儲存0代表到達了樹根。合併的兩個集合的方式就是找到兩個集合的樹根,然後讓其中乙個數根指向另乙個樹根即可。

typedef int disjset[numsets+1];  

typedef int settype;

void initialize(disjset s)

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

settype find(elementtype x, disjset s)

靈巧合併演算法:上面的合併演算法相當隨意,它就是把第二棵樹作為第一棵樹的子樹來完成合併操作。有乙個簡單的改進方法是總是讓較小的樹成為較大的樹的子樹,這種方法叫做union-by-size,如下圖所示union-by-size可以降低樹的深度,每個節點的深度都不會超過o(logn)。

為了實現這種方法,必須記錄每一棵樹的大小。我們可以另每乙個根節點的陣列元素表示樹的大小的賦值,非根節點不變,依舊表示其父節點。這其實是把上面方法的陣列中的0的位置做了一些利用。

另一種方法是union-by-height,也就是說我們把高度較淺的樹作為高度較深的樹的子樹。亦即根節點記錄的是樹的高度的負值。

編碼實現:

同樣這也非常容易實現,高度不相同時,低的指向高的,高的不用更新,相同時指向任意乙個,然後高度+1。

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

}

路徑壓縮:隨著樹的加深,find操作的時間會增加。如果find操作比union操作多的多的話,那麼運算時間會相當糟糕,比快速查詢還要差。而且從上面可以看出,union演算法的改進比較困難,因此我們應該嘗試去使find更加高效。這就引入了path compression。

路徑壓縮:在find操作期間執行與union操作無關,路徑壓縮的效果是從x到根節點的路徑上的每乙個結點都使它的父節點成為根節點。

編碼實現:

要讓經過的每乙個路徑都指向根節點,只要返回的時候,讓該節點中儲存的父親節點更新為返回值即可,由於等號運算子返回右值。所以可以寫為連等。

/*路徑壓縮*/

settype find(elementtype x, disjset s)

路徑壓縮演算法是與union-by-size相相容的,與union-by-height並不完全相容,因為路徑節點直接指向了根節點,改變了樹的高度。不過我們無需修改合併**。把原來儲存的高度當做秩處理即可(秩指示有多少節點連線在其上)。該書中有非常詳細的一段關於秩的性質的證明,很遺憾我是在是看不懂。。

應用:

這個資料結構的目的是解決等價問題,那麼用來處理鏈結就是最方便了。在這裡可以用計算機網路的例子。

乙個例子是計算機網路和雙向連線表,每乙個連線將檔案從乙個計算機傳遞到另乙個計算機。現在的問題是能否將檔案從任意乙個計算機傳遞到另乙個任意的計算機,並且這個問題要on-line解決。

解決這個問題,就可以用到上面的資料結構。開始階段我們可以把每一台計算機放到他自己的集合中,要求兩台計算機傳遞檔案當且僅當這兩台計算機在同乙個集合中。因此傳輸檔案能力相當於乙個等價關係。當我們需要傳輸檔案時,檢驗兩個計算機是否在同乙個集合裡,是的話就傳輸檔案,否的話,就用union方法把它們合併到乙個集合中,然後傳輸檔案。

總結:

不相交集學的比較鬱悶,因為中間一大段證明,然後還讀不明白。好在最後的例子比較簡單。網上找了找別人的部落格,發現也沒有什麼新的內容,都是本書上的東西直接抄到了部落格上。因此,我這篇部落格也是直接把書上的東西給挪了過來(實際上用的別人的部落格,反正和書一模一樣。。)。

資料結構與演算法分析 不相交集類

不相交集類是解決等價問題的一種有效資料結構,實現簡單,很少,速度快。等價關係 對於任意一對元素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,等價類是...

資料結構與演算法分析(四) 不相交集

乙個集合s,集合中乙個元素a。a的等價類是s的乙個子集,該子集包含所有與a有關係的元素。等價類形成是對s的乙個劃分且s中的每乙個成員恰好出現在乙個等價類中。這樣,判斷a與b是否有關係,只需要判斷a與b是否在乙個等價類中即可。對於集合s劃分,取任意兩個等價類,si與sj,如果si sj 則稱這些集合不...

資料結構 不相交集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屬...