22. 并查集
一、什么是并查集
并查集(Disjoint Set)是一种数据结构,用于管理一组不相交的集合,并支持两种主要操作:
- 查找(Find) :确定一个元素属于哪个集合,或者判断两个元素是否属于同一个集合。
- 合并(Union) :将两个不同的集合合并为一个集合。
并查集的核心思想是通过树形结构来表示集合,其中每个集合由一个根节点代表,根节点通常是集合中的一员,而且是自己的父节点。
二、创建并查集
DisjointSet * CreateDisjointSet(void)
{
DisjointSet * S= (DisjointSet *)calloc(MAX_SIZE, sizeof(DisjointSet));
for (int i = 0; i < MAX_SIZE; i++)
{
S[i].Data = i;
S[i].Parent = -1;
}
return S;
}
二、集合的查找
/**
* @brief 查找某个元素所在的集合
*
* @param S 并查集
* @param X 要查找的元素
* @return int 如果找到返回集合的根结点的下标,否则返回-1
*/
int Find(DisjointSet S[], ElementType X)
{
int i = 0, j = 0;
for ( i = 0; i < MAX_SIZE && S[i].Data != X; i++);
if (i >= MAX_SIZE)
{
return -1;
}
j = i; // X的下标
for (; S[i].Parent >= 0; i = S[i].Parent); // 找到X所属的集合的根结点的下标i
// 路径压缩
while (j != i)
{
int t = S[j].Parent;
S[j].Parent = i; // 直接将j的父结点指向根结点
j = t;
}
return i;
}
三、集合的并运算
分别找到 X1 和 X2 两个元素所在集合树的根结点。如果它们不同根,则将其中一个根结点的父结点指针设置为另一个根结点的数组下标。
/**
* @brief 合并两个集合
*
* @param S 并查集
* @param X 集合1中的元素
* @param Y 集合2中的元素
*/
void Union(DisjointSet S[], ElementType X, ElementType Y)
{
int Root1 = 0, Root2 = 0;
Root1 = Find(S, X);
Root2 = Find(S, Y);
if (Root1 != Root2)
{
if (S[Root1].Parent > S[Root2].Parent) // Root2的集合结点数多
{
S[Root2].Parent += S[Root1].Parent; // 累计结点总数
S[Root1].Parent = Root2; // 小树合并到大树
}
else
{
S[Root1].Parent += S[Root2].Parent;
S[Root2].Parent = Root1;
}
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)