并查集

并查集

解决元素分组问题

不相交的集合,两种操作

1.合并(Union)

2.查找(Find)

实现

  • 初始化

    fa数组记录父节点,初始化时父节点为自己

for i in range(n):
    fa[i] = i
  • 查询

    递归访问知道父节,父节点的父节点为自己,即fa[x] == x

def find(x):
	if fa[x] == x:
		return x
	else:
		return find(fa[x])
  • 合并

    找到两个集合的代表元素,将前者的父节点设为后者

    fa[find(i)] = find(j)
    

效率提升

  • 路径压缩

    希望每个元素到根节点的路径尽可能短

    在查询过程中,将沿途的每个节点的父节点都设为根节点

def find(x):
    if fa[x] == x:
        return x
    else:
        fa[x] == find(fa[x])
        return fa[x]
  • 效率的进一步提升(rank的引入)

    把简单的树往复杂的树上合并,使合并后到根节点距离变长的节点数少

    用数组rank记录每个根节点对应的树的深度,初始时所有元素的rank为1,

    合并时比较两个根节点,把rank较小者往较大者上合并

    rank合并

    def merge(i, j):
        x = find(i)
        y = find(j)
        if rank[x] <= rank[y]:
            fa[x] = y
        else:
            fa[y] = x
        if rank[x] == rank[y] and x != y:
            rank[y] += 1
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值