并查集
并查集是一种树型的数据结构,用于处理一些不相交集合(Disjoint Sets)的合并及查询问题。常常在使用中以森林来表示。
并查集是一种特殊的树形结构。其主要应用在集合论中。
在集合论中,判断两个点是否在同一集合是一件不简单的事情。在成千上万的数据里,判断两点是否在同一集合是很耗费时间的。因此,引入了并查集的思想。
并查集是一种树形结构,一棵树就是一个集合。判断两个点是否在同一集合中只需判断两个点的根节点是否为一个。如果要将两个集合合并为一个集合,也只需要将这两棵树合并为一棵,省时省力。
在这也会遇到一个问题,在建树的过程中,可能会有某一棵子树度很小导致其深度很大,就像一个线性表一样,这样在寻找根节点是无疑会增加查找时间,因此在进行树的合并时,要比较两棵树的深度,深度小的合并在深度大的树上。如果两棵树深度相同,则随意选一棵树做根树。
在这里,需要两个辅助数组,一个记录,每个节点的双亲节点,一个记录每个节点的深度。
// 初始化双亲数组,每个节点开始默认无双亲,故双亲为-1
// 每个节点默认深度为0
void InitParents(int parents[], int ranks[])
{
for(int i = 0; i < VERTCES; ++i)
{
parents[i] = -1;
ranks[i] = 0;
}
}
// 寻找该节点的根
int FindRoot(const int parent[], int x)
{
int root_x = x; // 初始化根为自己
while (parent[root_x] != -1) // 如果没有找到根,则寻找其双亲节点
{
root_x = parent[root_x];
}
return root_x; // 返回根节点
}
// 如果返回1,证明两个点分属于不同的集合,合并成功
// 如果返回0,证明两个点分属于不同的集合,合并失败
int UnionVertices(int parents[], int ranks[], int x, int y)
{
int x_root = FindRoot(parents, x); // 寻找x节点的根
int y_root = FindRoot(parents, y); // 寻找y节点的根
if(x_root == y_root) return 0; // 如果连个节点在同一棵树中,合并失败
// 比较两棵树的深度,深度小的合并在深度大的树上。如果两棵树深度相同,则随意选一棵树做根树。
else
{
if(ranks[x_root] > ranks[y_root])
{
parents[y_root] = x_root;
}
else if(ranks[y_root] > ranks[x_root])
{
parents[x_root] = y_root;
}
else
{
parents[x_root] = y_root;
++ranks[y_root];
}
return 1; // 合并成功
}
}
来源:CSDN
作者:渣渣酱Z
链接:https://blog.csdn.net/qq_44733706/article/details/103795934