之前听到室友提到过并查集,是一种数据结构,当时也不忙着找工作,所以也没去了解。
最近开始准备笔试了,感觉到了自身的菜,这不又遇到并查集了。赶忙去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