並查集基本操作及其優化

2022-05-20 20:59:40 字數 2566 閱讀 2291

麻麻,我們班的孩子都分為好幾個幫派,我要怎麼做才能知道他們總共分了有幾個幫派呀,我要怎麼才能知道他們有沒有人同時在兩個幫派呀;

接下來就進入我們的並查集專題,英文名稱union-find。

並查集是一種用於不相交集合的資料結構,並查集通過幾個操作來建立,修改,查詢和維護一些不相交的集合,一般用於不相交集合的合併問題,他也衍生出許多其他的應用,圖論中就會用並查集判環的操作,並查集還有著其他更為廣泛

的應用。

由於計算機經常會遇到資料量很大的情況,或者要反覆查詢某個元素所屬的集合,這類問題並查集統統搞定。

首先我們介紹一下他的基本操作:

init_set(v):建立集合操作,初始化每個元素單獨成為乙個集合。

find(v):查詢操作,我們用乙個集合中其中乙個元素的下標來表示這個集合,用二叉樹表示的話就是二叉樹的根,這個函式會返回v的最上層節點,即這個二叉集合數的根。

join(x, y):合併操作,將包含x集合和y集合的兩個集合合併為乙個新的集合。

is_same(u, v):查重操作,如果元素u和v在同乙個集合中則返回true;否則返回false。

下面我們給出這些操作的基本**:

1 #include 2

using

namespace

std;34

const

int maxn = 1e6 + 5;5

intn, head[maxn];67

void

init_set()

1011

int find(int

u) 15

16void join(int x, int

y) 20

21int is_same(int u, int

v)

下面給出乙個並查集的樣例:

以5個結點為例,圓圈內為結點的標號,我們用head陣列記錄每個結點的父親結點,head[i]表示i結點的父親節點的標號,當head[i] = i時,結點i的父節點是它本身,那麼i的所在的樹的根就是i。

初始化,head[i] = i,他們分別獨立成為乙個集合,分別作為自己的父節點。

init:

head[ i ] = i;

合併1和2時,2的父節點變為1,head[2] = 1, 此時有

如果我們現在分別查詢1和2結點所在樹的根節點,1結點所在的樹的根節點為1,2結點所在樹的根節點也是1,也就是說1和2此時位於根結點為1

的同一顆樹內。

接下來我們合併1和3,讓head[3] = 1,即使得3的父節點為1,有

head[1] = 1; head[2] = 1, head[3] = 1, head[4] = 4, head[5] = 5;

很明顯能知道1,2,3的最頂層節點都是1。

我們在合併4和5,讓4的父節點變為5,即head[4] = 5;

最後我們合併5和3,讓5的父節點為3,即head[5] = 3。可以得出如下的圖。

在上述演算法中很容易可以看出,每個結點都有乙個根結點,而兩個集合合併時會以其中乙個集合的根節點為新集合的根節點將另乙個集合插入,即形成了一顆二叉樹。

觀察上述演算法,可以發現基本所有操作都是基於find函式的,所以我們可以想可不可以有優化呢?我們發現初始化每個結點只進行一次,但是find和join都會進行多次,所以如果程式很大的話跑起來非常吃力。

下面我們就介紹兩種對該演算法的優化:

路徑壓縮:這種策略非常的簡單高效。正如下面的**中,在find操作之後,使用這種策略會使得查詢路徑中的每個結點直接指向根結點,路徑壓縮並不需要改變其餘的任何東西。

1 int find(intu) 

按秩合併:這種做法就是使具有較少結點的樹的根指向具有較多結點的樹的根。對於每個結點,我們維護乙個rank值,通過比較rank值我們進行相應的操作。

1 #include 2

using

namespace

std;34

const

int maxn = 1e6 + 5;5

intn, head[maxn], rank[maxn];67

void

init_set() 12}

1314

int find(int

u) 18

19void join(int x, int

y) 28}29

30int is_same(int u, int

v)

後續跟進並查集的相關題目......

並查集 並查集的基本操作總結

並查集的定義 並 union 合併 查 find 查詢 集 set 查詢 並查集的實現 int father n 使用乙個陣列記錄 father 1 1 1的父節點是本身 father 2 1 2的父節點是1 並查集的初始化 for int i 1 i n i 並查集的查詢 int findfath...

親戚 並查集 (內附並查集基本操作)

問題描述 何氏家族人員過於龐大,要判斷兩個是否是親戚,確實還很不容易,現在給出某個親戚關係圖,求任意給出的兩個人是否具有親戚關係。規定 x和y是親戚,y和z是親戚,那麼x和z也是親戚。如果x,y是親戚,那麼x的親戚都是y的親戚,y的親戚也都是x的親戚。輸入格式 第一行 三個整數n,m,q n 200...

並查集及其應用

並查集 union find sets 是一種簡單的用途廣泛的集合.並查集是若干個不相交集合,能夠實現較快的合併和判斷元素所在集合的操作,應用很多,如其求無向圖的連通分量個數 最小公共祖先 帶限制的作業排序,還有最完美的應用 實現kruskar演算法求最小生成樹。其實,這一部分 演算法導論 講的很精...