表示互斥集合(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 *****disjointset
互斥集合的優化:
如果最後生成高度為n-1的樹,則是鍊錶,那麼合併和查詢運算都會耗費o(n)的運算時間。
最簡單的方法是,合併兩個樹時,把高度更低的樹新增到高度更高的樹,以限制樹高的增加
struct optimizeddisjointset {
vectorparent, rank;
*****disjointset(int n) : parent(n) , rank(n, 1) {
for (int i=0; iint 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)
另一種優化方法是路徑壓縮優化
示例:判斷圖的連通性
示例:追蹤最大集合
互斥 軟體演算法
標籤 空格分隔 作業系統 互斥 軟體方法的實現方式能夠解決併發程序在乙個或者多個共享記憶體的處理器上執行的問題。這些方法通常是基於在訪問記憶體是基本互斥條件的假設。即,儘管訪問的順序沒有具體安排,同時訪問記憶體中的同乙個位址的操作被記憶體仲裁序列化 沒有丟失 此外,沒有考慮硬體 作業系統或是程式語言...
排序演算法集合
氣泡排序 public static int maopao int param return param 快速排序 public static int quick int param,int left,int right return param 分割陣列,相當於分治演算法,快速排序的核心 priv...
排序演算法集合
從未排序的集合中找出乙個元素,依次與已排序的集合元素進行比較,如果滿足規則,小於或是等於,直接插入,依次迴圈,直至待排序集合元素為空。清單.插入排序 直接插入排序 param arr public void insertsort int arr 從待排序元素集合中,找出其中最大或是最小的元素,插入到...