一. 并查集的介绍
1.并查集的简单介绍
并查集是一种树型的数据结构,用于处理一些不相交集合的合并及查询问题。并查集跟树有些类似,只不过她跟树是相反的。在树这个数据结构里面,每个节点会记录它的子节点。在并查集里,每个节点会记录它的父节点【1】。
并查集的精髓在于,两块集合(区域)有没有相交,以及要不要联通两块区域(集合)。参考树的结构,把元素挂到父节点下,若两个元素的父节点相同,则是同一块区域,两个元素的父节点不相同,则不是同一块区域。
以上图为例,1和2是同一片区域,3和4是同一片区域,5自己是一片区域,那么以上总共有三个区域。
2.并查集的典型使用场景
(1)最大岛屿面积(leetcode695)
0代表水,1代表陆地,求最大的岛屿数量(斜方向不算相交),那么图中最大面积是6(橘黄色)
(2)岛的数量(leetcode200)
这是并查集的典型使用场景,求连通分量,和(1)差不多,但是更简单
(3)省份数量(leetcode547)
在左图中,城市1和城市2是联通的,所以左图共有两个省份。
在右图中,城市和城市都不是联通的,所以共有三个省份。
二. 并查集的主要构成和实现方式
1. 主要构成
(0)总体构成
- 并,代表合并
- 查,代表查找
- 集,代表一个集合,这个集合中,大家的父节点都指向一个地方,即每个节点会记录它的父节点
(1)数据结构实现(HashMap版本)
让子节点指向父节点,可以用HashMap实现,即让Key指向value。
class UnionFind {
private Map<Integer,Integer> father;
}
加入father现在有三个entry,1->2,2->3,4->5.那么它的图示是这样子的:
(2) 元素添加的过程
以用HashMap的方式实现为例,那么添加一个新的元素时,它的父节点是null
public void add(int x){
if(!father.containsKey(x)){//从来没有在father中出现过
father.put(x,null);
numOfSets++;//联通区域需要加1
}
}
添加一个新的元素时,它的父节点也可以是它自己。
public void add(int x){
if(!father.containsKey(x)){//从来没有在father中出现过
father.put(x,x);
}
}
这两种方式都是可以的,下面我们以第一种为例。
添加过程: