将展示三种不同的并查集实现,通过这样的演化过程来体会并查集的思想。
三种实现里,都用到了一个id数组,但是具体的含义略有不同。

quick-find

这种实现里,id数组长度为N,如果pq是相连的,那么它们的id数组里的值相同,即id[p] == id[q]

所以对于find函数,找到该元素的上级。

// 初始化
public QuickFindUF(int N) {id = new int[N];for(int i = 0; i < N; i++) {id[i] = i;}
}
public int find(int p) {return id[p];
}
// 将p和q放到同一个组件内:联合
public void union(int p, int q) {int pID = find(p);int qID = find(q);// 如果已经相同,表示已经在同一个组件,无需再联合if (pID == qID) return;for(int i = 0; i < id.length; i++) {if(id[i] == pID) id[i] = qID; // 将pID组件元素全都交给qID吧,这是任意的,可以反过来全部交给pID}
}

这种写法,查询pq是否连通是很快的,是O(1)时间复杂度,而连接起来则是O(N)时间复杂度。这还是单次操作,也就是说,总体来看,Union的操作需要O(N^2)复杂度。

现在我们把注意力转向优化Union操作。

quick-union

这里的id数组是有额外含义的,id[i]的值是i元素的父亲。那么,按照这个逻辑推演,i元素的根就是id[id[...id[i]...]],一直往前,直到该值不再变化为止。

所以,判断pq是否在一个组件内,只需要各自找到自己的root值,判断它们的root值是否相等即可。

public int find(int p) {while(p != id[p]) p = id[p]; // 一路向上return p;
}
public void join(int p, int q) {int pRoot = find(p);int qRoot = find(q);if (pRoot == qRoot) return;id[pRoot] = id[qRoot]; // 直接将其中一个root值变成另外一个的小弟
}

weighted quick-union

在上面join时,只是随意将其中一个对象的根变成另一个的小弟,没有进行过滤,这样导致的结果是,树可能会很不平衡,从而在查找时耗时很长。

改进也很简单,跟踪一下树的尺寸,将小一点的树连接到大一点的树,即小一点的作为小弟即可。

public class WeightedQuickUnionUF {private int[] id;private int[] sz; // size of component for rootsprivate int count; // number of componentspublic WeightedQuickUnionUF(int N) {count = N; // 初始时有N个组件id = new int[N];sz = new int[N];  for(int i = 0; i < N; i++) {id[i] = i;sz[i] = 1;}}public int count() {return count;}public boolean connected(int p, int q) {return find(p) == find(q);}private int find(int p) {while(p != id[p]){p = id[p];}return p;}public void union(int p, int q) {int i = find(p);int j = find(q);if (i == j) return;if (sz[i] < sz[j]) {id[i] = j;sz[j] += sz[i];} else {id[j] = i;sz[i] += sz[j];}count--; // 执行一次union,才需要减一次}
}

到此为止,我们学习了三种方式,逐渐优化。但是还有进一步的可能,那就是路径压缩

路径压缩非常简单,只需要额外的一行即可:

private int find(int p) {while(p != id[p]) {id[p] = id[id[p]];p = id[p];}
}

END.

并查集--Java实现相关推荐

  1. HYSBZ - 1050(旅行comf 并查集Java实现)

    HYSBZ - 1050(旅行comf Java实现) 原题地址 解法:枚举每一条边,对于这条边,我们需要找到集合中和其值相差最小的最大边,这个集合是指与包括i边在内的ST联通集.对于这一要求,我们只 ...

  2. hdu1181变形课dfs/bfs/并查集三种解法(java)

    题目链接 Problem Description 呃-变形课上Harry碰到了一点小麻烦,因为他并不像Hermione那样能够记住所有的咒语而随意的将一个棒球变成刺猬什么的,但是他发现了变形咒语的一个 ...

  3. java最简单的并查集(不想交集合)以及杭电1272

    并查集要有的一些属性:value:表示当前值,指针:(不一定是指针)指向父节点. 还有一个属性number:表示该树存在的总个数.(也可以用深度表示).我用小树插在大树上. 如果是普通数字表示的树,可 ...

  4. [Leedcode][JAVA][第200题][岛屿数量][DFS][BFS][并查集]

    [问题描述] 第200题 岛屿数量 给你一个由 '1'(陆地)和 '0'(水)组成的的二维网格,请你计算网格中岛屿的数量.岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成 ...

  5. 堆的应用--并查集解决“擒贼先擒王”问题(JAVA)

    现在有10个强盗. 1号强盗与2号强盗是同伙. 3号强盗与4号强盗是同伙. 5号强盗与2号强盗是同伙. 4号强盗与6号强盗是同伙. 2号强盗与6号强盗是同伙. 8号强盗与7号强盗是同伙. 9号强盗与7 ...

  6. 挑战程序设计竞赛(算法和数据结构)——14.1互质的集合(并查集)的JAVA实现

    题目与思路: 代码: import java.util.Scanner; import java.util.Vector;public class DisjointSet {public static ...

  7. java并查集_一个非常实用而且精妙的算法-并查集(java语言实现)

    在学习数据结构的时候,老师多少会提到并查集,他的应用也是超级广泛.本文首先会通过案例来对并查集有一个介绍.然后给出并查集的java实现. 一.并查集原理 话说在江湖上有很多门派,这些门派相互争夺武林霸 ...

  8. hdu dfs入门java_hdu1181变形课dfs/bfs/并查集三种解法(java)

    题目链接 Problem Description 呃-变形课上Harry碰到了一点小麻烦,因为他并不像Hermione那样能够记住所有的咒语而随意的将一个棒球变成刺猬什么的,但是他发现了变形咒语的一个 ...

  9. 【数据结构与算法基础】并查集原理、封装实现及例题解析(C和java)

    前言 数据结构,一门数据处理的艺术,精巧的结构在一个又一个算法下发挥着他们无与伦比的高效和精密之美,在为信息技术打下坚实地基的同时,也令无数开发者和探索者为之着迷. 也因如此,它作为博主大二上学期最重 ...

最新文章

  1. 如何区别一幅图像是否是黑白图像
  2. display: inline-block;下增加overflow:hidden;产生高度问题
  3. boost::range模块tokenized相关的测试程序
  4. nginx操作指南之二
  5. 暴力破解(初级)以及弱口令工具的使用
  6. UVA 12298——Super Poker II
  7. 信息学奥赛一本通(2056:【例3.7】最大的数)
  8. raspberry pi_前5名:替代密码,Raspberry Pi进入太空等等
  9. Extjs 从grid中导出Excel表格。后台为C#(绝对好用)
  10. 蓝桥杯 卡片换位(bfs)
  11. 接口接收数据_基于原语的千兆以太网RGMII接口设计
  12. 译码器(24译码器,38译码器)笔记
  13. Idea查看 破解码
  14. javascript页面刷新的几种方法
  15. DDR3的配置及仿真教程
  16. 计算机符号的名字,符号网名大全
  17. DBeaver设置Maven镜像仓库
  18. android的se模式,Android中的SE 模块化LG G5 SE评测
  19. ArcGIS模型构建器前提条件的应用(附省界县点练习数据)
  20. Windows系统安装搭建ios开发环境

热门文章

  1. C++ Primer Plus学习(六)——分支语句和逻辑运算符
  2. 【学习OpenCV4】图像的模糊处理方法(均值滤波与高斯模糊)
  3. OpenCV入门: Mat数据类型及其转换,访问
  4. idea查看git分支快捷键_开发常用Git/Linux/idea命令快捷键总结(持续更新)
  5. kettle 插入更新 数据增量_kettle基于时间戳增量更新
  6. python自动化测试流程_接口自动化基本流程(python)
  7. qdebug 调试 输出乱码_Python里三个最高逼格的调试神器
  8. 文本文件 java_Java入门:读写文本文件
  9. struts2登录注册示例_Struts 2文件上传示例
  10. Python字符串translate()