什么是并查集
并查集是线性表的一种应用,是一种树型的数据结构,用于处理一些不相交集合(Disjoint Sets)的合并及查询问题。常常在使用中以森林来表示。集就是让每个元素构成一个单元素的集合,也就是按一定顺序将属于同一组的元素所在的集合合并。
结构
上面已经说明并查集是一种树型结构,所以可通过数组或者链表来实现,阿导在网上搜索了一下基本示例基本是通过数组来实现。
这样比较好模拟这种结构,下标为当前元素,然后数组里面的内容也为其组内成员。下面阿导以高度合并并查集为例
并查集的特性
-
树型的数据结构
-
最优情况下每个节点都指向根节点
-
每个集有不同的代表
-
具有传递性
操作
判断两个元素是否属于同一组
:public void isConnected(int x, int y)
直接查找到并查集的根就好了,若相等则在同一个组,否则不在同一个组。
合并两个元素所在的组
:public void unionElements(int x, int y)
首先查询到两个元素的根,若相等则本身就在一个组无需处理,若不等则进行合并操作,首先判断两个组的树的高度,将矮的树和并到高的树,那样根的高度不会改变,若两个树的高度相等,则将作为根的高度自增加一处理
完整代码
package com.qucheng.qingtian.wwjd.datastructure;
/**
* 并查集
*
* @author 阿导
* @CopyRight 万物皆导
* @Created 2019-12-04 16:49:00
*/
public class DaoUnionFindSet {
/**
* 当前下标的父亲是谁
*/
private int[] parent;
/**
* 当前树的高度
*/
private int[] rank;
/**
* 初始化数目
*/
private int size;
/**
* 初始化集合
*
* @param size
* @return
* @author 阿导
* @time 2019/12/4 :00
*/
public DaoUnionFindSet(int size) {
this.size = size;
this.parent = new int[size];
this.rank = new int[size];
for (int i = 0; i < size; i++) {
parent[i] = i;
rank[i] = 1;
}
}
/**
* 查询当前元素的根
*
* @param cur
* @return int
* @author 阿导
* @time 2019/12/4 :00
*/
private int findParrent(int cur) {
if (this.parent[cur] == cur) {
return cur;
}
//压缩路径,第二次查询可以直接返回x的根而不用递归
return this.parent[cur] = findParrent(this.parent[cur]);
}
/**
* 判断两个元素是否存在同一个集合
*
* @param x
* @param y
* @return boolean
* @author 阿导
* @time 2019/12/5 :00
*/
public boolean isConnected(int x, int y) {
return this.findParrent(x) == this.findParrent(y);
}
/**
* 合并两个元素所在的组
*
* @param x
* @param y
* @return void
* @author 阿导
* @time 2019/12/5 :00
*/
public void unionElements(int x, int y) {
// 获取 x 的根
x = this.findParrent(x);
// 获取 y 的根
y = this.findParrent(y);
// 若相等则就在同一组,不用处理
if (x == y) {
return;
}
// 若 y 的高度比较大,则将根的值设为 y,因此高度不会更改
if (this.rank[x] < this.rank[y]) {
this.parent[x] = y;
return;
}
// 否则根的节点设置成 x
this.parent[y] = x;
// 要是两者高度一样, 则势必高度会增加 1
if (this.rank[x] == this.rank[y]) {
rank[x]++;
}
}
}
关注点
- 并查集的操作
主要包含合并元素所在的组和判断两个元素是否在同一个组
- 如何压缩路径
在查询根的时候,将当前下标的内容设置为数组内容里面下标的数组内容,即 this.parent[cur] = findParrent(this.parent[cur])