算法导论之用于不相交集合的数据结构
不相交集合,即集合內元素無交集。在一些具體應用中,需將n個不同的元素分成一組不相交的集合。不相交集合的兩個重要操作,找出給定元素所屬的集合和合并兩個集合。為支持不相交集合的操作,需要設計和維護數據結構來滿足。導論中給出了鏈表和有根樹兩類數據結構來支持不相交集合的操作。
1、不相交集合的基本定義
不相交集合數據結構保持一組不相交的動態集合S={S1, S2,…, Sk}。每個集合通過一個代表來識別,代表即集合中的某個成員。選擇代表成員視乎具體應用,如選擇最小元素。
集合中的每一個元素是由一個對象表示的。設x表示一個對象,支持以下操作:
1)Make-set(x):建立一個新的集合,其唯一成員就是x。各集合是不相交的,所以x沒有在其他集合中出現過;
2)Union(x,y):將包含x和y的動態集合(Sx和Sy)合并成一個新的集合(并集SxUSy),當然Sx和Sy是不相交的。
3)Find-set(x):返回一個指針,指向包含x的唯一集合的代表。
分析不相交集合數據結構運行時間,主要考察兩個參數:
1)Make-set操作的次數n;
2)執行Make-set、Union、Find-set操作的總次數m,其中Union操作至多為n-1,因包含Make-set操作,所以m>=n。
2、不相交集合的一個應用
不相交集合數據結構的應用之一:用于確定一個無向圖中連通子圖的個數。算法上,首先將每個定點v置于各自的集合中,即執行Make-set操作;接著,對每一條邊(u,v)進行合并,即Union操作,當然包含u和v的集合是不相交的,對每條邊處理后,兩個頂點在同一連通子圖中的,其對應對象也在同一個集合中;最后,通過Find-set操作好處頂點是否在同一連通子圖中。
3、不相交集合鏈表數據結構
每一個集合用一個鏈表表示,鏈表作為不相交集合的數據結構,其每一個對象都包含一個集合成員、一個指向包含下一個集合成員的對象的指針、指向代表的指針;而每個鏈表都包含head指針和tail指針,head指向鏈表的代表,tail指向鏈表中最后的對象。鏈表中對象以任何次序出現,確保第一個對象就是所在集合的代表即可。
用鏈表實現不相交集合數據結構,Make-set和Find-set操作都只需O(1)時間。按照上面定義的n和m參數,執行Union操作(作用于n個對象上,包含m個操作序列)的運行時間是,一個操作的平攤時間是。
我對導論中的鏈表設計有點疑問,為什么每個對象指向代表的指針,不改為指向下一個對象的指針呢?這樣在合并操作時,只要更改一個鏈表頭尾指針,鏈表中每個對象不用更新。是否有其他因素考慮,比如別的操作性能更好,但暫時沒理解到。
對于Union合并操作,還給出一種加權合并啟發式策略,就是把較短的表拼接到較長的表。因為Union操作時,要拼接的鏈表,每個對象都要更新其指向代表對象的指針,這更新就和鏈表的長度成線性關系,所以短的鏈表去拼接,時間有優勢。應用加權啟發式策略,m個操作序列只需要O(m+nlgn)時間。
問題是:如何識別出較短長度的鏈表?
4、不相交集合有根樹數據結構
用有根樹表示集合,樹中的每個結點都包含集合的一個成員,每棵樹表示一個集合,群樹構成森林。每棵樹的根就是鏈表的代表,并且指向自己作為父結點。Make-set創建一個顆僅包含一個結點的樹。Find-set是沿著父結點指針一直找下去,直至找到樹根為止,查找路徑上訪問過的所有結點構成了查找路徑(find path),這里不明白的是,如果有分叉,順著父結點查找如何找到呢?Union操作使一顆樹的根指向另一個樹的根。
通過兩種啟發式策略來改進運行時間:
1)按秩合并:和鏈表中的加權合并思路一致,將較少結點的樹的根指向包含較多結點的樹的根。具有較小秩的根在Union操作中藥指向具有較大秩的根。
2)路徑壓縮:在Find-set操作中,使查找路徑上的每個結點都指向根節點。這個好理解,就是n個元素的集合,1個根,其他n-1個都是子女,互相構成兄弟,只有2層深度樹。
當同時使用按秩合并和路徑壓縮時,最壞情況運行時間為,其中是一個增長極其緩慢的函數,在任意可想象的不相交集合數據結構應用中。
對作用于n個元素上的m個不相交集合操作,聯合使用按秩合并和路徑壓縮啟發式的運行時間是界。導論中證明了是增長極其緩慢的函數。
證明的界是用平攤分析中的勢方法,證明是增長極快函數的逆函數。有趣的是這個增長盡快的函數。計算機算法基礎,之所以離不開數學,就在于任何算法的合理性(時間界運行性能)都需要數學的證明,當然設計算法(或說是模型)也需要數學基礎,否則就是無根之萍。
每種算法,每種數據結構,都尤其特定應用場合,所以在實際應用中,改良甚至創新都是必要的,但都要基于扎實的數學理論基礎。一種算法、一種數據結構,可以說是一種模型,是一種在應用中歸納升華出來的一種理論,可以應用于同類場合。當然關乎到數學基本問題,比如集合論對計算機理論的支持。總結
以上是生活随笔為你收集整理的算法导论之用于不相交集合的数据结构的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java-POI操作excel遇到文本字
- 下一篇: Java序列化和反序列化小记