Disjoint set(並查集) data structure
不相交集合(disjoint-set datastructure)資料結構又被稱為並查集(union-find data structure)資料結構。
涉及到將n 個不同的元素分成一組不相交的子集合(disjoint subset)。 所謂的不相交(disjoint), 又被稱為nonoverlapping subset。 並查集(亦稱為不相交集合) support 2個重要的operations:
(1)Find (x)操作: 尋找給定的元素屬於哪一個(唯一的)子集合。 這個Find 操作的返回的含有x的子集合S中 一個能夠代表這個子集合S的item(一般是S的最小的成員)。 我們可以通過比較2個Find 操作, 即find(x) 和 find(y) 來比較x 和 y 是否在同一個子集合中。
(2)Union 操作: 將兩個subset 合併成一個更大的subset。
除了上述的兩個操作, 還有一個操作叫做makeSet(x), 該操作的作用是建立一個新的集合, 它的唯一的成員(因而為代表)是x。因為各個集合是不相交的, 所以x 不會出現在別的集合中。
具有上述三個重要的關於並查集合的操作, 那麼眾多的partition problem 都能夠得到解決。
建立一個disjoint-set data structure 的最簡單的方法就是對於每一個set, 我們用linked list 實現它。 每一個list 的head 的element 作為代表代表著這個list(當然也就是代表著這個subset)。
makeSet 操作就是建立一個具有one element的 list 。 Union 操作就是將2個list 合併稱為一個list。 這是一個時間複雜度為O(1)的操作(constant-time operation)。
然而使用連結串列去實現每一個子集合的缺點就是導致Find 操作的時間複雜度為O(n)。
不相交集合森林(disjoint-set forests)
所謂的Disjoint-set forest, 就是將每一個set 用樹結構(tree data structure)(不一定是二叉樹, 也可能是多叉樹) 實現(represented。 樹的每一個節點都holds a reference to its parrent node。 這是由 Bernard A. Galler and Michael J. Fischer 在1964年發明的。
在disjoint-set forest中, 每一個set 的representative 就是由這個set而建立起來的樹的根節點, Find 操作 是沿著parent nodes, 直至到達the root。 Union 是將一棵樹的根節點和另一棵樹的根節點合併起來。 組成一棵更大的樹。
相關的操作的實現過程如下:
上面使用樹, 樹的每個成員均指向它的父節點, 且每棵樹根是這棵樹的代表, 並且是其自己的父節點。 但是使用樹的這種表示的 直接演算法並不比使用連結串列 的直接演算法快, 因為我們建的樹的結構 是一棵高度不平衡(highly unbalanced)的樹, 但是通過引入兩種啟發式的策略(“按秩合併”(Union by rank) 和 “路徑壓縮”(path compression)), 我們可以得到一種漸進最優的 不相交集合 資料結構。
(1)策略一: 按秩合併(Union by rank)
這個方法是將一棵較小樹(即節點數少)的根結點 連線到 具有較大的樹的根節點上(attach the smaller tree to the root of the larger tree)。 因為影響各個操作(演算法)的是樹的深度, 所以將較小的樹新增到更深的樹的根上 並不會增加秩除非這兩個數的深度相同(秩會增加1)。
之所以使用“秩”這個術語而不是用“深度”, 是因為如果同時使用了路徑壓縮的策略, 秩 將不會與高度相同。 氮元素的秩 定義為0。 兩棵秩同為r 的樹合併為一個大樹的時候, 他們的秩為r + 1. 只使用按秩合併這個策略, 將會使得makeSet 和 Union 以及 Find 操作的最壞情況下的時間複雜度為O(logn)。 優化後的makeSet 和 Union 的虛擬碼如下:
第二個優化演算法被稱為“路徑壓縮”。 這個優化策略是, 每當我們對樹結構執行Find操作的時候, 我們就使用路徑壓縮策略對flattening the structure of the tree 。 關鍵是在路徑上的每個節點都可以直接連線到根上。 為了達到扁平化樹結構的效果, Find 向上遞迴的traverse樹, 改變每一個節點的引用(parent Reference)到根節點()root。 最終我們會得帶一個much flatter 的樹。 對以後直接或者間接的引用這些節點加速。 改進後的Find操作如下:
關於Union-Find data structure 的實現
實現演算法程式碼如下:
例如, 具體的, 如下:
相關文章
- data structureStruct
- LeetCode-Data Stream as Disjoint IntervalsLeetCode
- 【題解】Solution Set - NOIP2024集訓Day8 並查集和可持久化並查集並查集持久化
- Data Structure_樹Struct
- sqrt-data-structureStruct
- 並查集到帶權並查集並查集
- 【並查集】【帶偏移的並查集】食物鏈並查集
- 並查集(一)並查集的幾種實現並查集
- 並查集(小白)並查集
- 3.1並查集並查集
- Structure of the Data Dictionary : Base Tables (258)Struct
- Half-Edge-Mesh-Data-StructureStruct
- 並查集(Union Find)並查集
- 並查集應用並查集
- The Door Problem 並查集並查集
- 並查集練習並查集
- 並查集的使用並查集
- 並查集—應用並查集
- 寫模板, 並查集。並查集
- 並查集跳躍並查集
- 各種並查集並查集
- data structure online videoStructIDE
- oracle10g data block structureOracleBloCStruct
- 並查集(二)並查集的演算法應用案例上並查集演算法
- Data block Structure and Row Piece Structure_20091209BloCStruct
- The Suspects-並查集(4)並查集
- [leetcode] 並查集(Ⅰ)LeetCode並查集
- [leetcode] 並查集(Ⅱ)LeetCode並查集
- [leetcode] 並查集(Ⅲ)LeetCode並查集
- 並查集演算法並查集演算法
- 並查集深度應用並查集
- 【轉】種類並查集並查集
- 並查集java實現並查集Java
- 並查集-Java實現並查集Java
- 並查集題目合集並查集
- 並查集以及應用並查集
- 並查集的應用並查集
- 暢通工程(並查集)並查集