并查集是一组对多个树(一般为2个)进行操作的算法。顾名思义,并查集的要点在于并和查,即合并和查找。
经过一些简单的优化,并查集的时间复杂度可以降到很低。
关于并查集的算法有查找,合并,删除,移动等。
查找
原理
从要查找的节点开始,一步步向上查找其上级节点直到根节点。
代码
int* root;//root[i]表示i的上级结点,根节点的root是它自己
int find(int x)
{
int i = x;
while (x != root[x]) {
x = root[x];//向上查找
}
root[i] = x;//注意这一步
return x;
}
路径压缩
注意上面代码中的这一步
root[i] = x;
这一步中使用了路径压缩。路径压缩是并查集中的重点,下面的大部分算法实现都是在应用了路径压缩的基础上完成的。
所谓路径压缩,就是将所有不与根节点直接相连的节点连到根节点上。
例如,看下面的树
这里3结点不直接与1结点相连,我们就可以用路径压缩的方式,将3节点的上级设为1结点
即root[3]=1;
路径压缩可以大幅降低并查集算法的时间复杂度。
合并
原理
合并就是将一棵树的根节点连接到另外一棵树的根节点上,这样就能将两棵树合并为一棵树
图中比较粗的线将第二棵树的根节点连接到第一棵树上。
代码
void merge(int x, int y)
{
if (find(x) != find(y)) {
root[find(y)] = find(x);
}
}
删除
原理
删除,是将某个叶节点从树上剔除,让这棵树上找不到这个结点。
在路径压缩的基础上,每个叶结点都直接与根节点相连,此时要删除一个叶节点,就直接将它的上级结点设为它自己,让它自己变成一棵树。
下图中,将3结点从树上删除。
代码
void delete_node(int x)
{
root[x] = x;
}
移动
原理
移动,就是将一棵树上的结点移动到另一棵树上去。
将要移动的结点的上级结点设置为另一棵树的根节点就可以。
代码
void shift(int i,int x)//i是要移动的节点,x是目的地的根节点
{
root[i] = x;
}
总结:从路径压缩这一核心部分能够看出,并查集适用于管理相互之间没什么关系的多个数据,并查集的时间复杂度很低,是一种很优秀的算法。
小白发文,如果能耐着性子看到这里的话,不如点个赞支持一下,非常感谢!!如果文中有什么问题或者不足的地方,请在评论区指出,谢谢各位大佬们了!!