並查集是一種維護集合的資料結構,他的名字取自「並」(union)、「查」(find)「集」(set)。並查集支援以下兩種操作:
合併:合併兩個集合
查詢:判斷兩個元素是否在乙個集合
使用乙個陣列實現:int father[n];
,其中father[i]表示元素i的父結點,這個父結點本身也屬於這個集合。
如果father[i] == i
,則說明元素i是這個集合的根結點,對於同乙個集合只存在乙個根結點,且將其作為所在集合的標識。
例如:
father[1]
=1;father[2]
=1;father[3]
=2;father[4]
=2;father[5]
=5;father[6]=5;
這樣就得到了兩個不同的集合
並查集的使用首先需要初始化father陣列,然後根據需要進行查詢或者合併的操作。
一開始每個元素都是各自屬於乙個集合,需要令所有father[i] = i
:
for
(int i =
0; i <= n; i ++
) father[i]
= i;
由於同一集合只存在乙個根結點,因此查詢操作就是對給定結點尋找對應根結點的過程。實現方式可是遞迴或者遞推,都是反覆尋找父結點,直到找到根結點(滿足father[i] == i
的結點)
遞推的**:
//findfather函式返回元素x所在集合的根結點的編號
intfindfather
(int x)
return x;
}
遞迴的**:
int
findfather
(int x)
簡便的寫法:
int
findfather
(int x)
合併指的是將兩個集合合併為乙個集合。題目中一般給出兩個元素,要求把這兩個元素所在的集合合併。一般是先判斷這兩個元素是否屬於同一集合,只有當這兩個元素屬於不同集合時,才合併,而且合併的過程一般是把其中乙個集合的根結點的父親設定為另乙個集合的根結點。
主要分為一下兩步:
判斷元素a、b是否屬於同一集合:呼叫findfather
函式對a、b查詢根結點,再判斷是否相同;
合併兩個集合:已經或得了兩個元素的根結點faa與fab,只需要令其中乙個根結點的父結點設定為另乙個結點,例如:father[faa] = fab;
void
union(int a,
int b)
注意:並非是將father[a] = b,而是對a、b所在集合的根結點進行操作。
路徑壓縮就是對並查集的查詢進行優化。
由findfather函式的目的就是查詢根結點,下面這個例子:
father[1]
=1;father[2]
=1;father[3]
=2;father[4]=2;
如果只是為了找到根結點,可以把操作等價變換成:
father[1]
=1;father[2]
=1;father[3]
=1;father[4]=1;
相當於把查詢結點的路徑上的所有結點的父親都設定為根結點,查詢的時候就不必一直回溯去找父親了,查詢的複雜度降為o(1)。這個轉換稱為路徑壓縮。
原先的findfather函式是從給定結點不斷或得它的父親最終找到根結點,轉換的過程可以分為以下兩個步驟:
按原先的寫法獲得x的根結點r
重新從x開始走一遍尋找根結點的過程,把路徑中經過的所有結點的父親都改為根結點r
int
findfather
(int x)
return x;
//返回根結點
}
這樣就可以在查詢的時候把尋找根結點的路徑壓縮了,可以把路徑壓縮後的並查集查詢函式均攤效率認為是o(1)。
路徑壓縮的遞迴寫法:
int
findfather
(int x)
}
acwing 836. 合併集合
注意:需要路徑壓縮,否則會超時
**:
//acwing 836. 合併集合
#include
using
namespace std;
const
int maxn =
1e5+10;
int n, m;
//n個數 m個操作
int father[maxn]
;//父結點
intfindfather
(int x)
}int
main()
if(op ==
'q')
}return0;
}
pat 1107 social clusters (30分)
pat 1114 family property
pat 1118 birds in forest
並查集學習筆記
並查集是一種用來管理資料分組狀況的資料結構,可以進行合併操作,但無法進行分割。並查集的結構 並查集也是用樹形結構來實現的,但不是二叉樹。每個資料,元素對應乙個節點,每個組對應一棵樹。並查集的實現 並查集有幾個基本操作初始化 查詢樹的根 合併x,y所屬集合 判斷x,y是否屬於同一集合。查詢是查詢樹的根...
並查集 學習筆記
並查集是由一組互不相交的集合組成的乙個集合結構,並在此集合上定義了運算union和find。即並查集中的元素本身是集合,他們是某個集合的子集,並查集是由這些集合組成的集合結構。並查集上有兩個最基本的運算,find和union。函式find搜尋給定元素i所在的子集合,並返回該自己喝 union運算將兩...
學習筆記 並查集
這是乙個可以實現合併與查詢 元素間關係判定 用來維護多集合 功能多樣化 的超牛批的可以動態維護的樹形結構。這個演算法只要是實現集合元素關係的型別都可以用到,又是線性時間複雜度,而且最關鍵的是它是個高階資料結構,翻譯過來就是這個可以動態維護,所以我覺得這個用途比單純的演算法要好,實際應用比較大,而且這...