并查集详解

之前听到室友提到过并查集,是一种数据结构,当时也不忙着找工作,所以也没去了解。

最近开始准备笔试了,感觉到了自身的菜,这不又遇到并查集了。赶忙去Google了一把。先是看leetcode对于并查集的解释。哦  “是一种树型的数据结构”,“用于处理一些不交集的合并以及查询问题。。”巴拉巴拉一大顿。

我天,这说的是人话吗,我感觉这东西应该不难,但被官方这么一解释,半懂不懂的,我彻底晕了。直接说大白话不好吗?或者举个例子更加直接明了。又去翻别的博客,发现有一个博客名字起的挺有意思——“傻子也能懂的并查集”。我要是看不懂我不就是傻子了么?我怀着沉重的心情打开了此博客,那个压力啊,大啊。

不过好在作者写的确实深入浅出,我看懂了。作为总结,我还是要写成一篇博客以便日后复习。大致内容和那篇博客上的相同,顺便也附上那篇博客的地址,以示尊敬。

https://segmentfault.com/a/1190000004023326

并查集其实就是一种树型的数据结构。对该数据结构主要有两种操作(1)查找,查找元素所对应的集合。一个集合即一棵树,用根节点来表示该集合。(2)合并,将两个集合合并成一个集合。

可以用两种方式来表示该数据结构:

1)结构体

class CheckSet:
    def __init__(self,data,rank,parent):
        self.data=data
        self.rank=rank
        self.parent=parent

2)数组表示(长度相等)

data=[] #数据值
rank=[]  #节点在树种的层次
parent=[] #父节点所在位置

当问题较为简单时推荐用数组,当问题较为复杂时推荐使用结构体。

首先根据问题初始化数据,data,rank,parent

1、通过并查集查找元素所在集合

由于仅有根节点的parent为自身,当parent[x] == x时,及找到该集合对应的根节点

def find(x):
    while parent[x] != x:
        x = parent[x]
    return x
#也可以用递归

路径压缩版本的查找

def find(x):
    t = x
    while parent[t] != t:
        t = parent[t]
    i = x
    while i != t:
        j = parent[i]
        parent[i] = t
        i = j
    return t

2、合并两个集合

假设两个集合的代表元(根)分别为x,y。则仅需一步操作 parent[x]=y 或者 parent[y]=x。但是这样可能增加树的深度。为了使合并后的树不产生退化,即使得树中左右子树的深度之差尽可能小。比较两棵树的深度,若rank[x]<rank[y] (根节点的rank为树的深度?),则parent[x]=y,否则 parent[y]=x。即谁深度小谁做子节点。

def union(i,j):
    x = find(i)
    y = find(j)
    if x==y:return x
    else:
        if rank[x]<rank[y]:
            parent[x]=y
            rank[x]+=1
            retrun y
        else:
            parent[y]=x
            rank[y]+=1
            return x    
原文地址:https://www.cnblogs.com/bianque/p/13568461.html