并查集
介绍
1.树型的数据结构
2.可进行操作
(1)查询元素p和元素q是否属于同一组
(2)合并元素p和元素q所在的组
结构
1. 每个元素都唯一的对应一个结点
2. 每一组数据中的多个元素都在同一颗树中
3. 一个组中的数据对应的树和另外一个组中的数据对应的树之间没有任何联系
4. 元素在树中并没有子父级关系的硬性要求
路径压缩算法优化
1.将非根节点的所有节点直接指向根节点,在同组(树)的节点,统一以根节点作标识,不需要一级一级向上查询
2.加权标记法
(1)将树中所有节点都增设一个权值,用以表示该节点所在树的元素个数
(2)在合并操作的时,通过这个权值的大小,把较小树合并到较大树
代码实现
public class DisjointSet {
public int[] father;//记录结点元素和该元素所的父结点
public int[] number;//存储每个根结点对应的树(组)中元素的个数
public int group;//记录并查集中数据的分组个数
//初始化并查集
public DisjointSet(int capacity) {
this.group = capacity;//初始情况下,每个元素都在一个独立的分组中,并查集中的数据默认分为capacity个组
number = new int[capacity];
father = new int[capacity];
//初始情况下,i索引处存储的值就是i,索引处的值为该组的父节点,索引视作储存元素
for (int i = 0; i < capacity; i++) {
father[i] = i;
}
//初始情况下,每个节点都是独立的树(组),每组只有一个元素
for (int i = 0; i < number.length; i++) {
number[i] = 1;
}
}
//元素p所在分组的根节点
public int root(int p) {
//判断当前元素p的父结点father[p]是不是自身
if (p == father[p]) {
return p;//若p已经是根结点,返回p
} else {
// 路径压缩
// root 函数向上寻找根节点,father[p] 表示 p 的父节点
// 那么让 father[p] 直接获取 root 函数 返回的根节点,这样就让节点 p 的父节点 变成根节点
return father[p] = root(father[p]);
}
}
//把p元素所在分组和q元素所在分组合并
public void unite(int p, int q) {
int pRoot = root(p);
int qRoot = root(q);
//如果p和q已经在同一个分组中,则无需合并
if (pRoot == qRoot) {
return;
}
//如果p和q不在同一个分组,比较p所在树的元素个数和q所在树的元素个数,把较小的树合并到较大的树上
if (number[pRoot] < number[qRoot]) {
father[pRoot] = qRoot;
number[qRoot] += number[pRoot];//重新调整较大树的元素个数
} else {//number[pRoot] >= number[qRoot]
father[qRoot] = pRoot;
number[pRoot] += number[qRoot];
}
group--;//分组数量-1
}
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战