並查集的概念與演算法實現
1、定義
並查集支援查詢一個元素所屬的集合以及合併兩個元素各自所屬的集合等運算。當給出兩個元素的一個無序對(a,b),需要快速“合併”a和b所在的集合時,需要反覆“查詢”元素的集合,“並”、“查”和“集”三字由此而來。
2、應用
並查集主要用於處理一些不相交集合的合併及查詢問題,它可以高效的解決一些等價類問題。
3、實現
(1)並查集的樹結構型別定義
typedef int ElemType;
//union-find set
typedef struct UFSTNode
{
ElemType data;
int rank;
int parent;
}UFSTNode;
(2)並查集的建立
void MAKE_SET(UFSTNode ufs[], ElemType _data[], int n)
{
for (int i = 0; i < n; i++)
{
ufs[i].data = _data[i];
ufs[i].parent = i;
ufs[i].rank = 1;
}
}
(3)並查集的查詢
int FIND_SET(UFSTNode ufs[], int x)
{
while (x != ufs[x].parent)
x = ufs[x].parent;
return x;
}
(4)並查集的合併
void UNION(UFSTNode ufs[], int x, int y)
{
int s_x = FIND_SET(ufs, x);
int s_y = FIND_SET(ufs, y);
if (s_x > s_y)
ufs[s_y].parent = s_x;
else
{
ufs[s_x].parent = s_y;
if (ufs[s_x].rank == ufs[s_y].rank)
ufs[s_y].rank++;
}
}
4、測試
問題: 親威關係問題。現給出一些親戚關係的資訊,如Marry和Tom是親戚,Tom希
Ben是親戚等。從這些資訊中,推出Marry 和Ben是否是親戚。
輸入: 第一部分以N,M開始。N 為問題涉及的人的個數(1<=N<=20000),這些人的家
號為1,2,3,…,N。下面有M行(1<=M<=1000000),每行有兩個數a,b,表示已知 ai 和 bi 是親威。
第二部分以Q 開始。以下Q行有Q個詢問(1<=Q<=1000000),每行為ci,di,表示詢向
ci和di是否為親戚。
輸出: 對於每個詢問ci,di,若 ci 和 di 為親戚,則輸出"Yes”,否則輸出“No"。
輸入樣例:
10 7
2 4
5 7
1 3
8 9
1 2
5 6
2 3
3
3 4
7 10
8 9
#include <iostream>
using namespace std;
typedef int ElemType;
//union-find set
typedef struct UFSTNode
{
ElemType data;
int rank;
int parent;
}UFSTNode;
void MAKE_SET(UFSTNode ufs[], ElemType _data[], int n)
{
for (int i = 0; i < n; i++)
{
ufs[i].data = _data[i];
ufs[i].parent = i;
ufs[i].rank = 1;
}
}
int FIND_SET(UFSTNode ufs[], int x)
{
while (x != ufs[x].parent)
x = ufs[x].parent;
return x;
}
void UNION(UFSTNode ufs[], int x, int y)
{
int s_x = FIND_SET(ufs, x);
int s_y = FIND_SET(ufs, y);
if (s_x > s_y)
ufs[s_y].parent = s_x;
else
{
ufs[s_x].parent = s_y;
if (ufs[s_x].rank == ufs[s_y].rank)
ufs[s_y].rank++;
}
}
int main()
{
//input
const int n = 11, m = 7, q = 3;
const ElemType data[n] = {};
const int relate_set[m][2] = { {2, 4}, {5, 7}, {1, 3}, {8, 9}, {1, 2}, {5, 6}, {2, 3} };
const int query_set[q][2] = { {3, 4}, {7, 10}, {8, 9} };
//execute
UFSTNode* ufs = new UFSTNode[n];
MAKE_SET(ufs, const_cast<ElemType*>(data), n);
for (int i = 0; i < m; i++)
{
UNION(ufs, relate_set[i][0], relate_set[i][1]);
}
//output
for (int i = 0; i < q; i++)
{
if (FIND_SET(ufs, query_set[i][0]) == FIND_SET(ufs, query_set[i][1]))
cout << "Yes" << endl;
else
cout << "No" << endl;
}
//clear
delete[] ufs;
system("pause");
return 0;
}
參考文獻
[1] 李春葆.資料結構教程.清華大學出版社,2013.
相關文章
- 並查集(一)並查集的幾種實現並查集
- 並查集java實現並查集Java
- 並查集-Java實現並查集Java
- 簡單易懂的並查集演算法以及並查集實戰演練並查集演算法
- 並查集(二)並查集的演算法應用案例上並查集演算法
- 並查集演算法並查集演算法
- 並查集演算法Union-Find的思想、實現以及應用並查集演算法
- 演算法與資料結構之並查集演算法資料結構並查集
- 序列並查集的線性演算法並查集演算法
- 【並查集】一種與時間賽跑的巧妙演算法並查集演算法
- 【並查集】【帶偏移的並查集】食物鏈並查集
- 基於並查集的六度分隔理論的驗證與實現並查集
- 並查集到帶權並查集並查集
- [演算法學習筆記] 並查集演算法筆記並查集
- 並查集的使用並查集
- 查並集
- 3.1並查集並查集
- 並查集(小白)並查集
- [leetcode] 並查集(Ⅱ)LeetCode並查集
- [leetcode] 並查集(Ⅲ)LeetCode並查集
- [leetcode] 並查集(Ⅰ)LeetCode並查集
- 資料結構與演算法知識點總結(3)樹、圖與並查集資料結構演算法並查集
- 並查集的應用2並查集
- 淺談並查集並查集
- 食物鏈(並查集)並查集
- 並查集跳躍並查集
- 各種並查集並查集
- 寫模板, 並查集。並查集
- 並查集(Union Find)並查集
- The Door Problem 並查集並查集
- 並查集練習並查集
- 並查集應用並查集
- 並查集在實際問題中的應用並查集
- 【從蛋殼到滿天飛】JS 資料結構解析和演算法實現-並查集(二)JS資料結構演算法並查集
- Soso 的並查集寫掛了並查集
- 並查集的簡單應用並查集
- 面試常考演算法題之並查集問題面試演算法並查集
- 實驗七: 查詢演算法的實現演算法