并查集
定义
并查集是一种树型的数据结构,用于处理一些不相交集合(Disjoint Sets)的合并及查询问题。常常在使用中以森林来表示。
存储实现
- 逻辑结构:使用树结构表示集合,树的每个结点代表一个集合元素
- 物理结构:采用数组存储,使用双亲表示法(孩子指向双亲)
例
有三个整数集合:
*
S1={1,2,4,7}
*
S2={3,5,8}
*
S3={6,9,10}
逻辑结构
物理结构
下标 | Data | Parent |
---|---|---|
0 | 1 | -1 |
1 | 2 | 0 |
2 | 3 | -1 |
3 | 4 | 0 |
4 | 5 | 2 |
5 | 6 | -1 |
7 | 8 | 2 |
8 | 9 | 5 |
9 | 10 | 5 |
Parent:
- 负数表示根结点
- 非负数表示双亲结点的下标
集合的运算
结构定义
typedef struct {
ElementType Data;
int Parent;
} SetType;
查找集合
查找某个元素所在的集合,用根结点下标表示
算法:
- 从数组中找到该元素的下标
- 根据该元素的Parent找到树根结点的下标
// 在数组S中查找值为X的元素所属的集合
int Find(SetType S[], ElementType X) {
int i;
for (i = 0; i < MaxSize && S[i].Data != X; i++); // 将i定位到X所在下标
if (i > MaxSize) // 未找到X,返回-1
return -1;
for (; S[i].Parent >= 0; i = S[i].Parent); //将i定位到x所在集合的根结点下标
return i;
}
集合的并运算
基本实现
算法:
- 分别找到X1和X2两个元素所在集合树的根结点
- 如果它们不同根,则将其中一个根结点的父结点指针设置成另一个根结点的数组下标
void Union(SetType S[], ElementType X1, ElementType X2) {
int Root1, Root2;
Root1 = Find(X1);
Root2 = Find(X2);
if (Root1 != Root2) // 当X1和X2不属于同一集合时才需要合并
S[Root2].Parent = Root1;
}
优化
- 在存储时,使用Parent域进行集合数量的记录。例如1个元素,Parent为-1;7个元素Parent为-7
- 合并时,采用小的集合合并到相对大的集合中