1.并查集概述
并查集也被称为不相交数据结构,顾名思义,并查集主要操作是合并与查询,即若一个问题涉及多个元素,它们可划归到不同集合,同属一个集合内的元素等价(即可用任意一个元素作为代表,比如上述的互为亲戚即互相等价),不同集合内的元素不等价。
并查集问题涉及的元素初始时总是自己构成一个单元素集合,求解问题需要通过合并操作将等价元素归入一个集合中。为了能够合并等价元素,我们必须查询希望合并的对象元素属于哪个集合,以决定是否要执行合并。因此 主要操作就是「查询」与「合并」。
2.并查集详细解析
2.1并查集查询
对于查询操作,也就是确定x所在集合的代表。可以沿着parent[x]往树形结构上方移动,直到树的根节点。具体如下图所示,查找2节点的根节点是0
对于查询操作时,有时树的高度过高,为了加快查找速度,在查找根节点的过程中,顺便把子节点的父节点改为根节点
2.2并查集合并
对于合并操作,假设需要合并的两个集合分别为x和y,则只需要令
parent[x] = y 或者parent[y] = x
为了使树中的子树的深度差尽可能的小,对于每一个元素x,维护rank[x]为以x为根子树的深度,具体操作请查看代码
3.并查集代码
class Unionfind(object):
def __init__(self,data_list):
#父节点集合
self.parent = {}
#rank[x]为当前树结构的高度
self.rank = {}
#count为独立的集合
self.count = len(data_list)
#初始化并查集
for data in data_list:
self.parent[data] = data
#初始化的树的高度都为1
self.rank[data] = 1
def find(self,data):
#并查集是使用递归的方法
father = self.parent[data]
if(data != father):
father = self.find(father)
#一般在查找父节点时会进行路径压缩,把当前节点移动到父节点下面
self.parent[data] = father
return father
#并查集的通断
def is_connect(self,x,y):
#查看两个节点是否在同一个集合
if self.find(x) == self.find(y):
return 1
else:
return 0
#按照规模合并和路径压缩的方式优化并查集
def union(self,x,y):
#寻找根节点
x_root = self.find(x)
y_root = self.find(y)
if(x_root != y_root):
x_rank = self.rank[x_root]
y_rank = self.rank[y_root]
#根据树的高度进行路径压缩
if x_rank >=y_rank:
self.parent[y_root] = x_root
if x_rank == y_rank:
self.rank[x_rank]+=1
else:
self.parent[x_root] = y_root
#数据集减1
self.count -= 1
4.并查集编程练习
@LeetCode765.情侣牵手*
@LeetCode547.省份数量