并查集有两种在 merge() 中的优化
一种基于 size 的;
一种基于 rank 的,rank的优化更彻底;
并查集还有在 find() 中的优化,就是路径压缩
所有操作均基于 并查集路径压缩及实现的模板实现
基于size的优化:
这里先看一个简单的例子来理解优化过程
index | 1 | 2 | 3 | 4 |
---|---|---|---|---|
father | None | 1 | 1 | None |
首先进行合并操作
将1节点与4节点连通
相当于代码模板中的merge(1, 4)
index | 1 | 2 | 3 | 4 |
---|---|---|---|---|
father | 4 | 4 | 4 | None |
可以发现,这个结构的树的层相对较高,
若此时元素数量增多,这样产生的消耗就会相对较大
解决这个问题其实很简单:
在进行具体指向操作的时候先进行判断
把元素少的集合根节点指向元素多的根节点
能更高概率的生成一个层数比较低的树。
构造并查集的时需初始化数组size为[1]
(并在添加节点操作时添加元素1,用于记录每个节点的深度)
class UnionFind:
def __init__(self):
"""
记录每个节点的父节点
"""
self.father = {
}
self.size = [1]
在进行合并操作时
需根据两个元素所在树的元素个数不同判断合并方向
在merge中进行优化进行优化操作
具体方法
将判错功能独立出来
如果size[x]的元素个数(连通分量中的节点个数)大于size[y]中的
就将root_x, root_y进行互换再进行操作
(等价于让y的连通分量并入x为根节点的连通分量中)
def merge(self, x, y):
"""
合并两个节点
"""
root_x, root_y = self.find(x), self.find(y)
if root_x == root_y:
return