演算法導論之並查積

2022-05-24 09:33:09 字數 1567 閱讀 1012

今天有空把演算法導論的並查積那一章看了一下,最後一節因為牽涉到平攤分析那一塊兒所以沒法看。在此之前沒有學過並查積,不過感覺挺難得。其實想想也明白就該有這麼東西,因為很多地方都會用到這種演算法,雖然不知道是什麼,但是肯定有。看並查積是因為前天在poj做了個題,感覺暴力的思路可以得出正確答案,但是資料規模極大,懷著僥倖的心理sub後直接返回了乙個tle,比較悲劇,也不明白會跟並查積扯上什麼關係,上discuss裡面一看,原來得用並查積。那也不也不會。剛好dp看了幾天都煩了,今天就看了會兒並查積。

演算法導論上是21章-用於不相交集合的資料結構,國外的書上都是這麼說的。演算法導論上面講的比較詳細。根據我能記住的就是對乙個大的集合,初始的時候就是每個元素在乙個獨立的集合中。每個集合有個代表(沿用演算法導論上的名字),同意集合中的每個元素的代表就是集合的代表。初始的時候就是元素自己。然後根據元素之間的關係,合併集合。元素之間的關係即判斷他們的代表是否相同,相同就是乙個集合,如果不相同但是屬於乙個集合,就要把他們合併。實現並查積的資料結構可以是鍊錶和陣列。根據書上講得貌似時間耗費也不是相差很大,不過覺得用資料比較簡單。如果用鍊錶的話每個集合應該含有乙個頭元素和乙個尾元素。頭元素指向代表即第乙個元素,尾元素指向最後乙個元素。每個成員應該儲存代表指標這個屬性。用陣列實現的話就是用樹來形容集合。每個元素i設定乙個陣列p[i]是他的父親。初始化p[i]=i。

一般的集合根據輸入分為動態和靜態的。靜態的就是集合是固定的,可以在集合上進行運算。可以用深度優先或者廣度優先搜尋來求不相交集合。時間上應該比並查積要快。所謂動態的集合就是集合需要動態的維護,也就是說不知道集合到底有哪些元素,要根據輸入隨時調整集合的狀態。所以使用並查積能夠有效解決此類問題。下面主要講兩點,關於兩個元素是否屬於乙個集合的判定和集合的合併該如何優化的問題。時間複雜度就不做討論了。

這兩個子問題在時間上應該是此消彼長,這雖然是個比較模糊的概念,但是很明顯,如果find()花的時間長union就簡單了。關於這兩個問題大師們的理論已經足夠解決acm中遇到的問題了。不相交集合的鏈表示能夠改進的方法有一種加權合併啟發式策略,按我的理解就是把少的加到多的上去,減少時間。道理很簡單,把少的加到多的上去總比多的加到少的上去快吧。如果是有根樹的話,即用森林表示不相交集合,感覺要簡單的多,因為樹可以用陣列表示。時間上也可以得到改進。有兩種啟發式策略:(1)按秩合併。(2)路徑壓縮。第一種就跟鍊錶裡面講的差不多,秩表示節點高度的上限。在合併的時候把秩較小的根指向較大的根。聽起來比較簡單。路徑壓縮是一種非常簡單有效地方法。因為find中,把查詢路徑上所有節點都指向了根節點。說白了就是find遞迴執行了一遍直到遇到了根,再返回,更新沿途的每個節點,使其指向根。這個過程中秩是沒有變化的。然後就是union,union就是根據秩修改父節點罷了,因為現在父節點就意味著元素所在集合的代表,也就是根。union(x, y)的步驟就是把秩小的樹根指向秩大的樹根。如果相等的話,隨便挑乙個就行,然後把秩加上一,因為樹高變了。有的書上並不是這樣講的,比如資料結構與演算法分析-c語言描述上就是用了比的說法,但是大同小異吧。演算法設計上與演算法導論使用的方法是一樣的。

經過此番處理,基本上就能把同屬於一夥的元素標記出來了,但是一般最後要用乙個對每個元素用一次find操作來找到它的代表,因為合併過程中並沒有改變全部元素的代表指向,這個地方尤其需要注意。lrj的書上沒有做深入的說明,題目倒是巨難無比。如需更多了解可參照演算法導論。

演算法模版之並查集

簡介 並查集實質是一種樹形的資料結構,一般用於處理一些不相交集合的合併及查詢問題。在具體問題解決上,比如找公共祖先節點 檢查圖的連通性等等,用通俗點的語言來描述的話,例如乙個幫派 有點社會呀 a的大哥是b,b的大哥是c,c的大哥是d,此時a b c d互相是不認識的,假如發生了幫派爭鬥,b和d相遇了...

演算法學習之並查集

並查集是一種樹型的結構,常常用來處理一些不相交的集合的合併和查詢問題。查詢 確定元素所在的集合。合併 將兩個集合合併成乙個集合。查詢v所在集合的根節點 int find int v 合併 void merge int x,int y 優化1 int find int x k x while k r ...

演算法學習之 並查集

並查集用於解決連線類問題,判斷網路中節點間的連線狀態。與路徑類問題相比,並查集只回答了節點之間是否連通,而具體的連通路徑並不能確定,因此並查集在某些場景下非常高效。如前所述,此處的並查集實現只提供兩個介面 是否連線,元素合併。下面 使用乙個陣列來記錄每個元素所對應的類別,如果兩個元素的類別相同,則稱...