并查集解析

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.省份数量

5.并查集参考文档

1.@csdn python实现并查集
2.并查集从入门到出门

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值