下面是详细的内容讲解。
数据结构与算法之并查集(不相交集合)
什么是并查集?
并查集,也叫不相交集合,是一种树形的数据结构,用于处理一些不相交集合(Disjoint Sets)的合并及查询问题。常常是在使用 Kruskal 算法或者 Prim 算法来求解最小生成树(Minimum Spanning Tree)时用到的一种数据结构。
并查集的基本操作
- MakeSet(x):建立一个新的并查集,其中包含一个元素x。
- Union(x, y):将元素x和元素y所在的集合合并。
- Find(x):找到元素x所在的集合的代表,也就是集合中的“元老”。
并查集的具体实现
并查集以数组形式实现。每个数组元素都存储一个 parent 指针指向它的父亲节点(或者它自己表示该元素是一个集合的代表)。当且仅当两个元素在同一个集合中时,它们的 parent 指针才指向相同的值。
在实现过程中,我们通常将 parent 数组中的元素的值初始化为其本身,即 parent[x]=x,表示它们都是单独的集合。
下面是并查集的基本实现:
class UnionFind:
def __init__(self, n):
# 初始化
self.count = n
self.parent = [i for i in range(n)]
def find(self, p):
# 找到并返回p所在集合的代表
while p != self.parent[p]:
self.parent[p] = self.parent[self.parent[p]]
p = self.parent[p]
return p
def union(self, p, q):
# 将p和q所在的集合合并
root_p = self.find(p)
root_q = self.find(q)
if root_p == root_q:
return
self.parent[root_p] = root_q
self.count -= 1
在并查集中,所有元素最初都被视为在单独的集合中。通过调用 Union 方法,可以将两个集合合并。Find 方法用于查找元素所属的集合。
并查集的应用
并查集最常用于判断无向图中是否存在环。每当我们遍历到一条边 (u, v) 时, 如果 u 和 v 已经在同一个集合中了,则说明 Graph 中存在环。否则,我们就将 u 和 v 合并到一个集合中。
下面是一个示例:
class Solution:
def findRedundantConnection(self, edges):
uf = UnionFind(len(edges) + 1)
for edge in edges:
if uf.find(edge[0]) == uf.find(edge[1]):
return edge
uf.union(edge[0], edge[1])
return []
在这个示例中,我们需要在一个无向图中找到一条边,如果删掉这条边,这个图就可以变成一棵树。我们可以使用并查集来判断。
另一个应用示例:计算连通分量
如果需要计算无向图中的连通分量,那么可以使用并查集来实现。首先,我们将所有的点都建立一个集合,然后依次遍历每一条边。当发现某条边的两个端点在同一个集合中时,说明它们是连通的,不需要再进行任何操作。否则,我们就将它们合并到一个集合中,同时连通分量的数量要减一。
下面是一个示例:
def count_components(n, edges):
uf = UnionFind(n)
for edge in edges:
uf.union(edge[0], edge[1])
return uf.count
在这个示例中,我们需要计算给定无向图中的连通分量数量,可以先通过 UnionFind 类将所有的点都建立成一个集合,然后遍历每一个边,如果发现它们在不同的集合中,就将其合并到一个集合中。最后,将连通分量的数量返回。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:数据结构与算法之并查集(不相交集合) - Python技术站