假定有一組詞彙,其中有一些詞是同義詞,可以把意思不同的詞分別放到不同的集合中,構成一組不相交的集合,每個集合內部都是同義詞。最開始我們不知到哪些詞可以歸併到相同的組中,因此開始的時候它們每個詞為一組。然後我們再一一給出哪些詞是同義詞,據此將初始的組進行合併……直到最後同義詞都被合併到各自應該歸屬的組裡面。
講的簡單點,假定這些單詞是乙個個的整數,他們構成了一組不相交的動態集合 s=
,,每個集合可能包含乙個或多個元素,並選出集合中的某個元素作為代表。每個集合中具體包含了哪些元素是不關心的,具體選擇哪個元素作為代表一般也是不關心的。我們關心的是,對於給定的元素,可以很快的找到這個元素所在的集合(的代表),以及合併兩個元素所在的集合,而且這些操作的時間複雜度都是常數級的。
這就是並查集的問題,並查集的基本操作有三個:
makeset(s):建立乙個新的並查集,其中包含 s 個單元素集合。
unionset(x, y):把元素 x 和元素 y 所在的集合合併,要求 x 和 y 所在的集合不相交,如果相交則不合併。
find(x):找到元素 x 所在的集合的代表,該操作也可以用於判斷兩個元素是否位於同乙個集合,只要將它們各自的代表比較一下就可以了。
1.並查集的森林表示
並查集的實現原理也比較簡單,就是使用樹來表示集合,樹的每個節點就表示集合中的乙個元素,樹根對應的元素就是該集合的代表,如圖 1 所示。
圖 1 並查集的樹表示
圖中有兩棵樹,分別對應兩個集合,其中第乙個集合為
,代表元素是
a ;第二個集合為
,代表元素是
e 。
樹的節點表示集合中的元素,指標表示指向父節點的指標,根節點的指標指向自己,表示其沒有父節點。沿著每個節點的父節點不斷向上查詢,最終就可以找到該樹的根節點,即該集合的代表元素。
2.構造並查集並初始化
現在,假設使用乙個足夠大的的連續空間來儲存樹節點,那麼 makeset 要做的就是構造出如圖 2 的森林,其中每個元素都是乙個單元素集合,即父節點是其自身:
圖 2 構造並查集初始化
3.並查集的find操作
接下來,就是 find 操作了,如果每次都沿著父節點向上查詢,那時間複雜度就是樹的高度,完全不可能達到常數級。這裡需要應用一種非常簡單而有效的策略——路徑壓縮。路徑壓縮,就是在每次查詢時,令查詢路徑上的每個節點都直接指向根節點,如圖 3 所示。
圖 3 路徑壓縮
4.並查集的合併操作
最後是合併操作 unionset,並查集的合併也非常簡單,就是將乙個集合的樹根指向另乙個集合的樹根,如圖 4 所示。
圖 4 並查集的合併
這裡也可以應用乙個簡單的啟發式策略——按秩合併。該方法使用秩來表示樹高度的上界,在合併時,總是將具有較小秩的樹根指向具有較大秩的樹根。簡單的說,就是總是將比較矮的樹作為子樹,新增到較高的樹中。為了儲存秩,需要為節點增加乙個成員rank,並將其值初始化為 0。(樹的秩:從樹的根節點x到某一後代葉節點的最長簡單路徑上邊的數目)
5.源**
#include #include #include #include using namespace std;
const int max = 20; //節點總數
const int num = 50; //操作次數
//節點定義
class node
};//並查集類操作定義
class uf;
//建構函式,批量申請記憶體並初始化
uf::uf()
}//析構函式,釋放空間
uf::~uf()
//查詢本家族代表單詞
node* uf::find(node *r) else
}//合併兩個家族
void uf::unit(node *x, node *y) else
} }}//列印所有節點的資訊,以供參考(當max大於20時建議不要用該函式)
void uf::print()
cout << endl;
cout << "祖先:";
for(node* p = s; p < s + max; p++)
cout << endl;
cout << "大小:";
for(node* p = s; p < s + max; p++)
cout << endl;
cout << "秩: ";
for(node* p = s; p < s + max; p++)
cout << endl;
}//測試函式
int main()
}
並查集(不相交集合)
早上早早起來看kruscal的mst演算法,原來要用到不相交集合來實現。拿起 演算法導論 看完不相交集合這章,頓然茅塞頓開,終於完成並查集的基礎知識的學習。演算法導論 真是牛 不相交集合有兩種不同的實現,鍊錶表示和帶路徑壓縮的按秩合併策略。看到大家都比較喜歡用帶路徑壓縮的按秩合併策略,那麼我只認真研...
用於不相交集合的資料結構(並查集)
一,兩個重要操作 1 找出給定元素所屬的集合 2 合併兩個集合 二,原理 保持一組不相交的動態集合s 每個集合通過乙個代表來識別,代表即集合中的某個元素 三,操作 1 make set x 建立乙個新的集合,其唯一成員就是x 因各集合是不相交的,故要求x沒有在其他集合 現過 2 union x,y ...
不相交集合的資料結構 並查集
在介紹操作之前,我得先說說實現這些操作的背景。對於並查集中的每乙個集合,都有乙個代表,這個代表就是集合中的乙個元素,其表示了整個集合。打個比喻吧,最近召開了19大,各個代表都召集到了人民大會堂,假設每個代表都代表著某個省份的人去參加會議,比如我是江西的,江西省的人大代表就代表了江西人民參加會議進行投...