演算法:互斥集合
表示互斥集合(disjoint set)時,經常會使用另一種具有獨特形態的樹結構--並查集(union-find)資料結構。
互斥集合:
假設有n名客人蔘加聚會,主持人要求相同生日的人組成一隊。話音剛落,客人們立刻開始組隊。剛開始時,因為不知道哪位客人的生日與自己的生日相同,所以大家只能單獨徘徊。不過,只要找到1名相同生日的客人,兩人就會開始結伴移動。若發現另一個相同生日的隊伍,就會與這支隊伍合併。
應該使用何種資料結構表示這種情況呢?對參加聚會的全體客人的集合而言,隊伍是將些集合分割為若干部分的子集合。而每個隊由生日相同的客人組成,所以每名客人都不可能屬於一個以上的隊伍。這種沒有共同元素的子集合稱為互斥子集合,儲存這種資訊並對其進行操作的資料結構就是並杳集資料結構。
為了表示這種情況,首先需要把客人表示為0到n-1之間的元素,然後生成只包含1個元素的n個集合。兩名客人a和b的生日相同時,合併包含二者的集合。為了實現該過程,需要如下3種運算。
1、初始化:初始化為n個元素被包含於各自集合的形式
2、並集(union)運算:給出兩個元素a和b時,合併兩個元素所在集合
3、查詢(find)運算:給出了某個元素a時,返回此元素所在集合
利用陣列表示互斥集合:
利用一維陣列就能非常簡單地表示互斥集合。生成如下形式的陣列belongsTo。
belongsTo[i] = 第i個元素所屬的集合序號
此方式並集運算耗時,雖然查詢O(1)
利用樹結構表示互斥集合:
同屬於一個集合的元素繫結到一個樹結構。
struct NaiveDisjointSet {
vector<int> parent;
NaiveDisjointSet(int n) : parent(n) {
for (int i=0; i<n; i++) parent[i] = i;
}
int find(int u) const {
if (u == parent[u]) return u;
return find(parent[u]);
}
void merge(int u, int v) {
u = find(u); v = find(v);
if (u == v) return;
parent[u] = v;
}
};
互斥集合的優化:
如果最後生成高度為n-1的樹,則是連結串列,那麼合併和查詢運算都會耗費O(n)的運算時間。
最簡單的方法是,合併兩個樹時,把高度更低的樹新增到高度更高的樹,以限制樹高的增加
struct OptimizedDisjointSet {
vector<int> parent, rank;
NaiveDisjointSet(int n) : parent(n) , rank(n, 1) {
for (int i=0; i<n; i++) parent[i] = i;
}
int find(int u) const {
if (u == parent[u]) return u;
return parent[u] = find(parent[u]);
}
void merge(int u, int v) {
u = find(u); v = find(v);
if (u == v) return;
if (rank[u] > rank[v]) swap(u, v);
parent[u] = v;
if (rank[u] == rank[v]) ++rank[v];
}
};
時間複雜度:並集為O(lgn),查詢為O(lgn)
另一種優化方法是路徑壓縮優化
示例:判斷圖的連通性
示例:追蹤最大集合
相關文章
- 排序演算法集合排序演算法
- STL 演算法集合演算法
- 多執行緒互斥鎖訪問演算法(上)------Peterson演算法執行緒演算法
- 執行緒同步與互斥:互斥鎖執行緒
- JavaScript常見演算法集合JavaScript演算法
- 多執行緒互斥鎖訪問演算法(下)------Lamport演算法(麵包店演算法)執行緒演算法LAMP
- liteos互斥鎖(七)
- 互斥與獨立
- JavaScript資料結構與演算法——集合JavaScript資料結構演算法
- 演算法與資料結構之集合演算法資料結構
- Java 集合中的排序演算法淺析Java排序演算法
- 透過互斥鎖+條件量的方式實現同步與互斥
- C#互斥體——MutexC#Mutex
- 多工同步與互斥概念
- Python中的互斥鎖Python
- C++ 封裝互斥物件C++封裝物件
- 執行緒的互斥鎖執行緒
- 集合差異比較演算法及效能測試演算法
- 04 Javascript資料結構與演算法 之 集合JavaScript資料結構演算法
- JavaScript的資料結構與演算法(五) —— 集合JavaScript資料結構演算法
- 使用貪心演算法解決集合覆蓋問題演算法
- Go語言的互斥鎖MutexGoMutex
- 集合框架-TreeMap集合框架
- 集合框架-Set集合框架
- 集合框架-TreeSet集合框架
- 集合框架-Collection集合框架
- 集合框架-List集合框架
- 學習OpenCV:濾鏡系列(13)——計算模式演算法集合OpenCV模式演算法
- 互斥鎖mutex的簡單實現Mutex
- 實現TypeScript中的互斥型別TypeScript型別
- Linux之執行緒互斥鎖Linux執行緒
- windows多執行緒同步--互斥量Windows執行緒
- 特定的閂鎖和互斥場景
- 淺談程式同步和互斥的概念
- Python 執行緒同步與互斥Python執行緒
- 互斥鎖和條件變數 (轉)變數
- 【go】golang中鎖的用法-互斥鎖Golang
- python 協程 自定義互斥鎖Python