并查集
基础与数据结构
说明
维护元素所属的连通集合;路径压缩与按秩合并使操作接近常数时间。
分析
每个集合用一个代表根节点表示,Find 沿 parent 链寻找它。路径压缩缩短以后查询的路径,按秩合并避免树过高。
Union(0,2)先找根,再把2挂到0下面,二者Find相等。路径压缩会改写父指针,Find不一定是只读操作;秩控制合并方向,不是压缩后的精确高度,近常数指均摊反阿克曼复杂度。
查看图表代码
适用前提与边界
它擅长动态合并与连通性查询,但普通并查集不支持高效拆分已合并集合。 元素编号必须落在0到n-1;重复Union不改变集合,普通路径压缩实现不支持直接撤销合并。
示例输入与调用
go
groups := NewDSU(3)
groups.Union(0, 2)
fmt.Println(groups.Find(0) == groups.Find(2))运行输出
text
true完整 Go 示例
go
package main
import "fmt"
type DSU struct{ parent, rank []int }
func NewDSU(n int) *DSU {
d := &DSU{make([]int, n), make([]int, n)}
for i := range d.parent {
d.parent[i] = i
}
return d
}
func (d *DSU) Find(x int) int {
if d.parent[x] != x {
d.parent[x] = d.Find(d.parent[x])
}
return d.parent[x]
}
func (d *DSU) Union(a, b int) {
a, b = d.Find(a), d.Find(b)
if a == b {
return
}
if d.rank[a] < d.rank[b] {
a, b = b, a
}
d.parent[b] = a
if d.rank[a] == d.rank[b] {
d.rank[a]++
}
}
func main() {
groups := NewDSU(3)
groups.Union(0, 2)
fmt.Println(groups.Find(0) == groups.Find(2))
}继续阅读
- 系统学习
- 系统学习
- 系统学习