继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

并查集入门:基础概念与简单应用

海绵宝宝撒
关注TA
已关注
手记 453
粉丝 40
获赞 125
概述

并查集,一种高效解决集合问题的数据结构,特别适用于图论、网络连通性及竞赛编程领域。它通过提供初始化和合并集合的关键操作,支持快速判断集合并查找操作,优化路径压缩和按秩合并策略提升性能,广泛应用于集合划分、图的连通性判断等场景。

并查集入门:基础概念与简单应用

I. 并查集简介

并查集(Disjoint Set Union, DSU)是一种用于解决集合问题的数据结构,尤其在需要频繁操作的集合之间判断是否相交或合并集合时非常有效。并查集的核心在于提供两个主要操作:初始化(或创建)集合以及合并两个集合。它在图论、网络连通性问题、集合划分问题、以及各种竞赛编程中有着广泛的应用。

II. 并查集的实现

并查集可以使用数组或链表实现,下面分别介绍两种实现方式。

数组实现

数组实现中的每个元素指向其父元素。数组的长度等于需要管理的集合数目。

class UnionFind:
    def __init__(self, size):
        self.parent = list(range(size))
        self.rank = [0] * size

    def find(self, x):
        if self.parent[x] != x:
            self.parent[x] = self.find(self.parent[x])
        return self.parent[x]

    def union(self, x, y):
        rootX = self.find(x)
        rootY = self.find(y)
        if rootX != rootY:
            if self.rank[rootX] > self.rank[rootY]:
                self.parent[rootY] = rootX
            elif self.rank[rootX] < self.rank[rootY]:
                self.parent[rootX] = rootY
            else:
                self.parent[rootY] = rootX
                self.rank[rootX] += 1
链表实现

链表实现中的每个节点存储一个指向其父节点的引用,这使得查找操作更高效。

class Node:
    def __init__(self, value):
        self.value = value
        self.parent = self

    def find(self):
        if self.parent != self:
            self.parent = self.parent.find()
        return self.parent

class UnionFind:
    def __init__(self, size):
        self.nodes = [Node(i) for i in range(size)]

    def union(self, x, y):
        rootX = self.nodes[x].find()
        rootY = self.nodes[y].find()
        if rootX != rootY:
            self.nodes[rootX].parent = rootY

III. 查找操作详解

查找操作是递归地向上查找直到找到根节点,根节点的父节点是它自身。为了优化查找速度,通常采用两种技术:路径压缩按秩合并

路径压缩

在查找过程中,直接将节点连接到根节点,避免了通过中间节点的递归查找。

def find(self, x):
    if self.parent[x] != x:
        self.parent[x] = self.find(self.parent[x])
    return self.parent[x]
按秩合并

在合并时,将较低秩的根节点指向较高秩的根节点,以减少树的高度。秩可以表示为树的高度。

def union(self, x, y):
    rootX = self.find(x)
    rootY = self.find(y)
    if rootX != rootY:
        if self.rank[rootX] > self.rank[rootY]:
            self.parent[rootY] = rootX
        else:
            self.parent[rootX] = rootY
            if self.rank[rootX] == self.rank[rootY]:
                self.rank[rootY] += 1

IV. 合并操作详解

合并操作本质上就是将两个集合的根节点关联起来。在数组实现中,需要找到两个集合的根节点并进行连接;在链表实现中,查找根节点后直接进行连接。

V. 实例分析

为了更好地理解并查集的应用,我们来解决一个实际问题:判断图中的边是否形成环

def is_cyclic(self, edges):
    for u, v in edges:
        if self.find(u) == self.find(v):
            return True
        self.union(u, v)
    return False

在上面的示例中,我们通过is_cyclic函数检查图中的边是否形成环。如果在任何时候两个节点属于同一个集合,那么就存在环。

VI. 小结与拓展

并查集是一种非常高效的数据结构,尤其在处理大量集合操作时。通过路径压缩和按秩合并的优化,查找和合并操作的时间复杂度可以分别降低到接近常数级别。并查集在解决连通性问题、图论中的许多问题以及其他需要动态维护集合关系的场景中非常有用。为了进一步学习和拓展,并查集的变种,如支持快速查找但不支持合并操作的快速查找树(Quick Find),以及更高效的实现,如支持快速查询和合并的路径压缩和按秩合并的并查集,都是深入研究的方向。推荐进一步阅读关于数据结构和算法的在线课程或书籍,如慕课网上的相关课程,以获得更深入的理解和实践。

打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP