【算法學習】union-find算法

      看了算法4中1.5關於union-find算法的介紹還是蠻感興趣的,就在網上找了一些相關的博文看看,發現董的博客記錄的蠻好的,於是就想引用了,這位董叔設置了不讓選中複製的功能,可能不希望自己的心血被別人拿去享用吧,但是俺們乃苦逼學生一枚,斷不敢拿大牛的著作肆意妄爲,望不究俺轉文之過。以下爲董的博客的內容:

------------------------------------------------------------------------------------------------------------------

    1、   概述

      並查集(Disjoint set或者Union-find set)是一種樹型的數據結構,常用於處理一些不相交集合(Disjoint Sets)的合併及查詢問題。

    2、  基本操作

並查集是一種非常簡單的數據結構,它主要涉及兩個基本操作,分別爲:

     A. 合併兩個不相交集合

     B. 判斷兩個元素是否屬於同一個集合

  (1)合併兩個不相交集合(Union(x,y))

    合併操作很簡單:先設置一個數組Father[x],表示x的“父親”的編號。那麼,合併兩個不相交集合的方法就是,找到其中一個集合最父親的父親(也就是最久遠的祖先),將另外一個集合的最久遠的祖先的父親指向它。


    上圖爲兩個不相交集合,b圖爲合併後Father(b):=Father(g)

2)       判斷兩個元素是否屬於同一集合(Find_Set(x))

本操作可轉換爲尋找兩個元素的最久遠祖先是否相同。可以採用遞歸實現。

3、  優化

(1)       Find_Set(x)時,路徑壓縮

尋找祖先時,我們一般採用遞歸查找,但是當元素很多亦或是整棵樹變爲一條鏈時,每次Find_Set(x)都是O(n)的複雜度。爲了避免這種情況,我們需對路徑進行壓縮,即當我們經過”遞推”找到祖先節點後,”回溯”的時候順便將它的子孫節點都直接指向祖先,這樣以後再次Find_Set(x)時複雜度就變成O(1)了,如下圖所示。可見,路徑壓縮方便了以後的查找。


(2)       Union(x,y)時,按秩合併

即合併的時候將元素少的集合合併到元素多的集合中,這樣合併之後樹的高度會相對較小。

4、  編程實現
int father[MAX];   /* father[x]表示x的父節點*/
 
int rank[MAX];     /*rank[x]表示x的秩*/
 
 
 
void Make_Set(int x)
 
{
 
father[x] = x; //根據實際情況指定的父節點可變化
 
rank[x] = 0;   //根據實際情況初始化秩也有所變化
 
}
 
/* 查找x元素所在的集合,回溯時壓縮路徑*/
 
int Find_Set(int x)
 
{
 
if (x != father[x])
 
{
 
father[x] = Find_Set(father[x]); //這個回溯時的壓縮路徑是精華
 
}
 
return father[x];
 
}
 
/*
 
按秩合併x,y所在的集合
 
下面的那個if else結構不是絕對的,具體根據情況變化
 
但是,宗旨是不變的即,按秩合併,實時更新秩。
 
*/
 
void Union(int x, int y)
 
{
 
x = Find_Set(x);
 
y = Find_Set(y);
 
if (x == y) return;
 
if (rank[x] > rank[y])
 
{
 
father[y] = x;
 
}
 
else
 
{
 
if (rank[x] == rank[y])
 
{
 
rank[y]++;
 
}
 
father[x] = y;
 
}
 
}

5、  複雜度分析

空間複雜度爲O(N),建立一個集合的時間複雜度爲O(1),N次合併M查找的時間複雜度爲O(M Alpha(N)),這裏Alpha是Ackerman函數的某個反函數,在很大的範圍內(人類目前觀測到的宇宙範圍估算有10的80次方個原子,這小於前面所說的範圍)這個函數的值可以看成是不大於4的,所以並查集的操作可以看作是線性的。具體複雜度分析過程見參考資料(3)。

6、  應用

並查集常作爲另一種複雜的數據結構或者算法的存儲結構。常見的應用有:求無向圖的連通分量個數,最近公共祖先(LCA),帶限制的作業排序,實現Kruskar算法求最小生成樹等。

7、  參考資料

(1)       並查集:http://www.nocow.cn/index.php/%E5%B9%B6%E6%9F%A5%E9%9B%86

(2)       博文《並查集詳解》:http://www.cnblogs.com/cherish_yimi/

(3)       Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, and Clifford Stein. Introduction to Algorithms, Second Edition. MIT Press and McGraw-Hill, 2001. ISBN 0-262-03293-7. Chapter 21: Data structures for Disjoint Sets, pp. 498–524.

------------------------------------------------------------------------------------------------------------------

      自己還沒有修煉到自己寫這種博文的技術,現在也沒有太多時間寫博文了,就轉吧,回頭放假抽時間整理一下,權當複習了。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章