【数据结构与算法】并查集

本文介绍了并查集这种数据结构,主要用于处理分组问题和维护无向图的连通性。文章详细讲解了并查集的基本操作,如makeSet、find和unionSet,并提供了Python实现。通过一个朋友圈问题的LeetCode题目实例展示了并查集的应用。
摘要由CSDN通过智能技术生成

引言

在刷算法题的时候, 遇到了并查集这个数据结构。对这个数据结构不是特别熟悉,在这篇文章中专门整理总结一下。

这篇文章主要关注以下几点:

  1. 并查集可以用于哪些场景
  2. 并查集有哪些操作
  3. 并查集的简单实现方式
  4. 实际解决问题的案例

并查集的应用场景

个人理解,并查集最直接的应用,还是用于分组问题, 把一个几个分成若干个组, 每个组都有一个代表。 我们可能需要把两个组给合并然后重新选举一个代表, 也可能会在给定一个元素的场景下, 判断这个元素是否在某个组中。
看了一些参考资料, 并查集的主要用途有:

  • 维护无向图的连通性, 判断两个点是否在同一个连通块内。
  • 判断增加一条边是否会产生环。 (对这个用途还不是特别了解,后续研究)

并查集的操作

  1. makeSet()
    表示建立一个并查集,这通常是一个数组或者字典,我们可以用索引表示元素的id, 再用数组元素的值表示这个组的代码元素id。

  2. unionSet(x, y)
    把元素x 和元素y 的所在的集合合并。

  3. find(x)
    找到元素x所在的集合代表。

并查集的数据结构实现方式

我们来实现一下并查集的方法。

# 使用并查集的方法编程
class UnionFind:
    """
    * 这里并查集定义为一个字典
    * key是元素id, value 是这个组的父节点id, 也就是每个分组的代表。
    * 记录一下组的个数
    """
    def __init__(self):
        self.father = {}
        self.num_of_sets = 0
    """
    目的是返回元素x所在的组的代表
    * 第一步先找到树的根
    * 第二步, 每一次遍历父节点,所有节点的父节点都变为根节点
    这是在查找过程中不断的更新树。
    """
    def find(self, x): 
        root = x
        
        while self.father[root] != None:
            root = self.father[root]

        while x != root:
            original_father = self.father[x]
            self.father[x] = root
            x = original_father
        return root
    

    """
    unionSet 操作
    * 查询x,y两个节点的根节点, 如果不是在同一个组中,就合并, 其实就是把根节点设置为一个
    """    
    def merge(self, x, y):
        root_x, root_y = self.find(x), self.find(y)
        print(root_x, root_y)
        if root_x != root_y:  # 这里存疑, 应该是相等吧
            # print(root_x, root_y)
            self.father[root_x] = root_y
            self.num_of_sets -= 1
    """
    添加元素的操作也比较简单, 这个新元素就是根节点, 单独作为一个组。
    组的个数 加一。
    """
    def add(self, x):
        if x not in self.father:
            self.father[x] = None
            self.num_of_sets += 1

算法题目案例

题目:朋友圈问题, leetcode题目编号(#547),给定一个二维数组,isConnected[i][j]表示 i和j是不是朋友, 1表示是朋友。求朋友圈的个数。
思路: 遍历二维数组中的所有元素,对于每个人,先把这个人加入到并查集中, 再看看其他人和这个人是否是朋友,如果是,则执行合并操作。

uf = UnionFind()
for i in range(len(isConnected)):
    uf.add(i)
    for j in range(i):
        if isConnect[i][j]:
            uf.merge(i,j)

return uf.num_of_sets 

总结

并查集在图算法中也有很多的应用, 后续可以学习了解下。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值