在一些有N个元素构成的一些单元素的集合,需要反复查找一个元素在哪一个集合中,判断两个数是否属于同一个集合,以及合并两个集合。并查集是一种树型的数据结构。用于处理不相交的集合( disjoint sets)的合并以及查询问题。在使用时用森林表示。
如集合A={0,1,3,6} , B={ 2,4 7} , C={5,8,9}其A,B,C分别构成三棵树,A,B,C共同构成一个森林,并查集一般用数组存储,如数组father。father[i]表示i的父节点,当father[x]==x时,表示x是根结点。在查找元素属于哪一个集合时,采用路径压缩的办法,可以避免树退化为线性,以保证查找的效率。它使用的O(n)的空间,单次查找时间为O(a(n)),一般可认为是常数:
以下是A,B,C集合在father数组的存储:
| 0 | 0 |
| 1 | 0 |
| 2 | 2 |
| 3 | 0 |
| 4 | 2 |
| 5 | 5 |
| 6 | 0 |
| 7 | 2 |
| 8 | 5 |
| 9 | 5 |
#include<iostream>
using namespace std;
#define n 11
int father[n] = {0,0,2,0,2,5,0,2,5,5,9};
int getRoot(int x);
int Union(int x, int y);
int main(){
/*测试*/
int i,j;
cin >> i;
i = getRoot(i);
cout << i << endl;
Union(1, 10);
cin >> i;
i = getRoot(i);
cout << i << endl;
return 0;
}
int getRoot(int x){
int j = x,i;
while (father[x] != x) /*向上寻找根结点*/
x=father[x];
while (father[j] != x){ /*状态压缩*/
i = father[j]; /*记住j的父节点i*/
father[j] = x; /*将j直接连到根结点*/
j = i; /*更新j为j原来的父节点*/
}
return x; // 返回根结点
}
int Union(int x, int y){
x = getRoot(x);
y = getRoot(y);
if (x != y)
father[x] = y;
return y; //返回最后合并的根结点
}以上查找还可以使用递归的写法,这样getRoot函数如下:
int getRoot(int x){
if (father[x] != x)
father[x] = getRoot(father[x]); //状态压缩,将沿途结点都连接到根结点后
return father[x]; // 返回根结点
}以下实现集合的查找以及集合的并:
本文介绍了并查集这一数据结构的基本概念及其应用场景,详细解释了如何通过并查集进行集合查找与合并操作,包括使用路径压缩技术提高查找效率的方法。
1859

被折叠的 条评论
为什么被折叠?



