並查集(合併集合,查詢集合中的元素)

2022-09-14 23:42:29 字數 1695 閱讀 1712

定義:「合併集合」和「查詢集合中的元素」兩種操作的關於資料結構的一種演算法。

演算法:用集合中的某個元素來代表這個集合,該元素稱為集合的代表元

乙個集合內的所有元素組織成以代表元為根的樹形結構

對於每乙個元素 parent[x]指向x在樹形結構上的父親節點。如果x是根節點,則令parent[x] = x。

對於查詢操作,假設需要確定x所在的的集合,也就是確定集合的代表元。可以沿著parent[x]不斷在樹形結構中向上移動,直到到達根節點。

判斷兩個元素是否屬於同乙個集合,只需要看他們的代表元是否相同即可

包括對所有單個的資料建立乙個單獨的集合(即根據題目的意思自己建立的最多可能有的集合,為下面的合併查詢操作提供操作物件)

在每乙個單個的集合裡面,有三個東西。

集合所代表的資料。(這個初始值根據需要自己定義,不固定)

這個集合的層次通常用rank表示(一般來說,初始化的工作之一就是將每乙個集合裡的rank置為0)。

這個集合的類別parent(有的人也喜歡用set表示)(其實就是乙個指標,用來指示這個集合屬於那一類,合併過後的集合,他們的parent指向的最終值一定是相同的。)

(有的簡單題裡面集合的資料就是這個集合的標號,也就是說只包含2和3,1省略了)

初始化的時候,乙個集合的parent都是這個集合自己的標號。沒有跟它同類的集合,那麼這個集合的源頭只能是自己了。

(最簡單的集合就只含有這三個東西了,當然,複雜的集合就是把3指標這一項新增內容,如pku食物鏈那題,我們還可以新增enemy指標,表示這個物種集合的天敵集合;food指標,表示這個物種集合的食物集合。隨著指標的增加,並查集操作起來也變得複雜,題目也就顯得更難了)

對於合併操作,假設需要合併的兩個集合的代表元分別為x和y,則只需要令parent[x]= y或者parent[y]= x即可。為了使合併後的樹不產生退化,即使樹中左右子樹的深度差盡可能小,對於每乙個元素x,維護rank[x]為以x為根的子樹的深度。合併時,如果rank[x]

——結構體法——

#define max 10000

struct node

node[max];

/***查詢集合i(乙個元素是乙個集合)的源頭(遞迴實現)。

如果集合i的父親是自己,說明自己就是源頭,返回自己的標號;

否則查詢集合i的父親的源頭。

**/int get_parent(int x)

//合併集合

void union(int a,int b)

}

——陣列法——

int set[max];//集合index的類別,或者用parent表示

int rank[max];//集合index的層次,通常初始化為0

int data[max];//集合index的資料型別

//初始化集合

void make_set(int i)

//查詢集合i(乙個元素是乙個集合)的源頭(遞迴實現)

int find_set(int i)

//合併集合(將代表元合併即可)

void union(int i,int j)

}

並查集(合併,查詢)

並查集用於管理元素分組情況的資料結構,判斷某一組合是否存在於同一集合 擁有同一性質 樹形結構實現但非二叉樹,但是通過rank比較可以優化為類似平衡二叉樹 int par 1000000 int rank 1000000 統計樹的深度 int size 1000000 統計每一棵樹結點個數 void ...

並查集 合併集合,連通塊中點的數量

練習題 includeusing namespace std const int n 1e6 int n,m int p n 儲存每個點的祖宗節點 返回x的祖宗結點 路徑壓縮 int find int x int main return 0 給定乙個包含n個點 編號為1 n 的無向圖,初始時圖中沒有...

並查集合集

題目1 include include include include include includeusing namespace std const int maxn 1e6 10 int pre maxn maxx maxn num maxn int findfather int x whil...