并查集(Union Find)
Posted 文大侠
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了并查集(Union Find)相关的知识,希望对你有一定的参考价值。
算法背景
Union Find算法,中文并查集。主要用来解决图论中的连通判断问题,简单抽象问题为:
- 平面上有n个点
- 给定他们之间两两连接关系
要求输入任意两个点,判断他们是否能够有一条路径联通
算法步骤
一旦有连接,就把一个节点设为另一个节点的父节点,最终连通的点会构成一颗树。通过判断两个节点的根节点是否相同,即可判断是否连通。具体如下
- 初始化时,每个节点指向自己,也就是根节点
- 遍历给定的两两连接关系,分别找各自的根节点,将两个根节点连接起来
- 判断是否联通很简单,找两个点的根结点是否相同
整个过程是不断合并树的过程,为了保证更优的效率,两个优化点
- 合并树的过程尽量保证平衡,这里引入根节点权重,小树合并到大树上,也就是秩优化
- 查找过程尽量快,这里引入路径压缩,把查找过程中的节点全部直接挂到根结点上,相当于一个均摊的过程
参考 https://mp.weixin.qq.com/s/gUwLfi25TYamq8AJVIopfA
代码详解
type UF struct {
parent []int
sz []int
}
// 初始化union find
func getUF(n int) *UF {
parent := make([]int, n)
sz := make([]int, n)
for i := 0; i < n; i++ {
parent[i] = i // 初始化父节点指向自己,即根节点指向自己
sz[i] = i // 树高初始化为1
}
return &UF{parent, sz}
}
// 关联
func (u *UF) union(i int, j int) {
root_i := u.find(i)
root_j := u.find(j)
if root_i == root_j {
return
}
// 小树挂到大树上,秩优化
if u.sz[root_i] > u.sz[root_j] {
u.parent[root_j] = root_i
} else {
u.parent[root_i] = root_j
if u.sz[root_i] == u.sz[root_j] {
u.sz[root_j] += 1
}
}
}
// 查找根节点
func (u *UF) find(i int) int {
if u.parent[i] != i {
u.parent[i] = u.find(u.parent[i]) // 递归,路径压缩
}
return u.parent[i]
}
// 判断是否连通
func (u *UF) connected(i int, j int) bool {
root_i := u.find(i)
root_j := u.find(j)
return root_i == root_j
}
关联leetcode
leetcode关联题目参考 https://books.halfrost.com/leetcode/ChapterTwo/Union_Find/
- 源代码位置 https://github.com/JimWen/go-algo/tree/main/unionfind
原创,转载请注明来自
以上是关于并查集(Union Find)的主要内容,如果未能解决你的问题,请参考以下文章