时间复杂度:

  O(log*n),近乎是O(1)级别的

UnionFind 接口:

public interface UF {
int getSize();
boolean isConnected(int p, int q);
void unionElements(int p, int q);
}

第一种:

//quickFind
public class UnionFind1 implements UF{
//id 这个数组中并没有存储数据的值,而是存储了数据所在的集合编号
private int[] id; public UnionFind1(int size) {
id = new int[size];
for(int i = 0 ; i < id.length ; i ++) {
id[i] = i;
}
} @Override
public int getSize() {
return id.length;
} //查找元素p所对应的集合编号
private int find(int p) {
if(p < 0 || p >= id.length) {
throw new IllegalArgumentException("p is out of bound.");
}
return id[p];
} //查看元素p和q是否属于同一个集合
@Override
public boolean isConnected(int p, int q) {
// TODO Auto-generated method stub
return find(p) == find(q);
} //将p和q所属的集合合并
@Override
public void unionElements(int p, int q) {
// TODO Auto-generated method stub
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;
}
}
} }

第二种:

//QuickUnion
//一种孩子指向父亲节的树
public class UnionFind2 implements UF{ private int[] parent; public UnionFind2(int size) {
parent = new int[size]; //初始的时候每一个节点都指向他自己,每一个节点都是一棵独立的树
for(int i = 0 ; i< size ; i ++) {
parent[i] = i;
}
} @Override
public int getSize() { return parent.length;
} private int find(int p) {
if(p < 0 || p >= parent.length) {
throw new IllegalArgumentException("p is out of bound.");
}
while(p != parent[p]) {
p = parent[p];
}
return p;
} @Override
public boolean isConnected(int p, int q) { return find(p) == find(q);
} @Override
public void unionElements(int p, int q) { int pRoot = find(p);
int qRoot = find(q); if(pRoot == qRoot) {
return;
}else {
parent[pRoot] = qRoot;
} } }

第三种:

package UnionFind;

//使树的深度尽量保持较低水平
//节点总数小的那个树去指向节点总数大的那棵树
public class UnionFind3 implements UF { private int[] parent;
// sz[i]表示以i为根的的集合中元素的个数
private int[] sz; public UnionFind3(int size) {
parent = new int[size];
for(int i = 0 ; i < parent.length ; i ++) {
parent[i] = i;
sz[i] = 1;
}
}
@Override
public int getSize() {
// TODO Auto-generated method stub
return parent.length;
} private int find(int p) {
if(p < 0 || p >= parent.length) {
throw new IllegalArgumentException("p is out of bound.");
}
while(p != parent[p]) {
p = parent[p];
}
return p;
}
@Override
public boolean isConnected(int p, int q) { return find(p) == find(q);
} @Override
public void unionElements(int p, int q) {
int pRoot = find(p);
int qRoot = find(q); if(pRoot == qRoot) {
return;
}
if(sz[pRoot] < sz[qRoot]) {
parent[pRoot] = qRoot;
sz[qRoot] += sz[pRoot];
}else {
parent[qRoot] = pRoot;
sz[pRoot] += sz[qRoot];
} } }

第四种:

//基于rank的优化
//使深度小的那棵树指向深度大的那棵树
public class UnionFind4 implements UF { private int[] parent;
// rank[i]表示以i为根的的集合所表示的树的层数
private int[] rank; public UnionFind4(int size) {
parent = new int[size];
for(int i = 0 ; i < parent.length ; i ++) {
parent[i] = i;
rank[i] = 1;
}
}
@Override
public int getSize() {
// TODO Auto-generated method stub
return parent.length;
} private int find(int p) {
if(p < 0 || p >= parent.length) {
throw new IllegalArgumentException("p is out of bound.");
}
while(p != parent[p]) {
p = parent[p];
}
return p;
}
@Override
public boolean isConnected(int p, int q) { return find(p) == find(q);
} @Override
public void unionElements(int p, int q) {
int pRoot = find(p);
int qRoot = find(q); if(pRoot == qRoot) {
return;
}
if(rank[pRoot] < rank[qRoot]) {
parent[pRoot] = qRoot;
}else if(rank[pRoot] > rank[qRoot]){
parent[qRoot] = pRoot;
}else {
parent[qRoot] = pRoot;
rank[pRoot] += 1;
} } }

第五种:

//路径压缩
public class UnionFind5 implements UF{ private int[] parent;
// rank[i]表示以i为根的的集合所表示的树的层数
private int[] rank; public UnionFind5(int size) {
parent = new int[size];
for(int i = 0 ; i < parent.length ; i ++) {
parent[i] = i;
rank[i] = 1;
}
}
@Override
public int getSize() {
// TODO Auto-generated method stub
return parent.length;
} //这里添加路径压缩的过程
private int find(int p) {
if(p < 0 || p >= parent.length) {
throw new IllegalArgumentException("p is out of bound.");
}
while(p != parent[p]) {
parent[p] = parent[parent[p]];
p = parent[p];
}
return p;
}
@Override
public boolean isConnected(int p, int q) { return find(p) == find(q);
} //这里的rank不再是每个节点精准的深度,只是做为一个参考,由于性能考虑所以不维护rank
@Override
public void unionElements(int p, int q) {
int pRoot = find(p);
int qRoot = find(q); if(pRoot == qRoot) {
return;
}
if(rank[pRoot] < rank[qRoot]) {
parent[pRoot] = qRoot;
}else if(rank[pRoot] > rank[qRoot]){
parent[qRoot] = pRoot;
}else {
parent[qRoot] = pRoot;
rank[pRoot] += 1;
} } }

第六种:

//find过程中让每个节点都指向根节点
//路径压缩
public class UnionFind6 implements UF{ private int[] parent;
// rank[i]表示以i为根的的集合所表示的树的层数
private int[] rank; public UnionFind6(int size) {
parent = new int[size];
for(int i = 0 ; i < parent.length ; i ++) {
parent[i] = i;
rank[i] = 1;
}
}
@Override
public int getSize() {
// TODO Auto-generated method stub
return parent.length;
} //这里添加路径压缩的过程
//递归调用
private int find(int p) {
if(p < 0 || p >= parent.length) {
throw new IllegalArgumentException("p is out of bound.");
}
if(p != parent[p]) {
parent[p] = find(parent[p]);
}
return parent[p];
}
@Override
public boolean isConnected(int p, int q) { return find(p) == find(q);
} //这里的rank不再是每个节点精准的深度,只是做为一个参考,由于性能考虑所以不维护rank
@Override
public void unionElements(int p, int q) {
int pRoot = find(p);
int qRoot = find(q); if(pRoot == qRoot) {
return;
}
if(rank[pRoot] < rank[qRoot]) {
parent[pRoot] = qRoot;
}else if(rank[pRoot] > rank[qRoot]){
parent[qRoot] = pRoot;
}else {
parent[qRoot] = pRoot;
rank[pRoot] += 1;
} } }

java——并查集 UnionFind的更多相关文章

  1. 并查集(union-find)算法

    动态连通性 . 假设程序读入一个整数对p q,如果所有已知的所有整数对都不能说明p和q是相连的,那么将这一整数对写到输出中,如果已知的数据可以说明p和q是相连的,那么程序忽略p q继续读入下一整数对. ...

  2. 并查集 Union-Find

    并查集能做什么? 1.连接两个对象; 2.查询两个对象是否在一个集合中,或者说两个对象是否是连接在一起的. 并查集有什么应用? 1. Percolation问题. 2. 无向图连通子图个数 3. 最近 ...

  3. 并查集(Union-Find)算法介绍

    原文链接:http://blog.csdn.net/dm_vincent/article/details/7655764 本文主要介绍解决动态连通性一类问题的一种算法,使用到了一种叫做并查集的数据结构 ...

  4. 数据结构之并查集Union-Find Sets

    1.  概述 并查集(Disjoint set或者Union-find set)是一种树型的数据结构,常用于处理一些不相交集合(Disjoint Sets)的合并及查询问题. 2.  基本操作 并查集 ...

  5. 并查集 (Union-Find Sets)及其应用

    定义 并查集是一种树型的数据结构,用于处理一些不相交集合(Disjoint Sets)的合并及查询问题.常常在使用中以森林来表示. 集就是让每个元素构成一个单元素的集合,也就是按一定顺序将属于同一组的 ...

  6. 并查集(Union-Find) 应用举例 --- 基础篇

    本文是作为上一篇文章 <并查集算法原理和改进> 的后续,焦点主要集中在一些并查集的应用上.材料主要是取自POJ,HDOJ上的一些算法练习题. 首先还是回顾和总结一下关于并查集的几个关键点: ...

  7. 【LeetCode】并查集 union-find(共16题)

    链接:https://leetcode.com/tag/union-find/ [128]Longest Consecutive Sequence  (2018年11月22日,开始解决hard题) 给 ...

  8. 数据结构《14》----并查集 Union-Find

    描述: 并查集是一种描述解决等价关系.能够方便地描述不相交的多个集合. 支持如下操作    1. 建立包含元素 x 的集合  MakeSet(x) 2. 查找给定元素所在的集合 Find(x), 返回 ...

  9. 并查集(union-find set)与Kruskal算法

    并查集 并查集处理的是集合之间的关系,即‘union' , 'find' .在这种数据类型中,N个不同元素被分成若干个组,每组是一个集合,这种集合叫做分离集合.并查集支持查找一个元素所属的集合和两个元 ...

随机推荐

  1. 机器人自主移动的秘密:SLAM与路径规划有什么关系?(三)

    博客转载自:https://www.leiphone.com/news/201612/lvDXqY82OGNqEiyl.html 雷锋网(公众号:雷锋网)按:本文作者SLAMTEC(思岚科技公号sla ...

  2. loj10093 网络协议

    传送门 分析 第一问我们不难想出是缩点之后的新图中入度为0的点的个数,对于第二问,我们画一画可以发现最优策略就是对于每一个入度为0的点都有一个出度为0的点连向它,而对于每一个出度为0的点也一定连向一个 ...

  3. Git 之 初使用

    什么是Git? Git 是一个开源的分布式版本控制软件,用以有效.高速的处理从很小到非常大的项目版本管理. Git 最初是由Linus Torvalds设计开发的,用于管理Linux内核开发.Git ...

  4. sublime 配置 anaconda 环境

    安装清单: 软件列表: anaconda sublime text sublime插件列表: package control Conda 安装 anaconda https://www.continu ...

  5. [学习笔记]信号基本概念(中断和信号)/名称及常用信号/信号处理/signal函数实践

    1基本概念 中断 q  中断是系统对于异步事件的响应 q  中断信号 q  中断源 q  现场信息 q  中断处理程序 q  中断向量表 异步事件的响应:进程执行代码的过程中可以随时被打断,然后去执行 ...

  6. Android将程序崩溃信息保存本地文件

    大家都知道,现在安装Android系统的手机版本和设备千差万别,在模拟器上运行良好的程序安装到某款手机上说不定就出现崩溃的现象,开发者个人不可能购买所有设备逐个调试,所以在程序发布出去之后,如果出现了 ...

  7. js 代码收集

    //获取image src路径 $(".userImg").click(function(){ var imgsrc = $(this).attr("src") ...

  8. 读取txt里面的数据进行计算

    双在论坛上找到一个问题,有关读取txt里面的数据进行计算的问题. 尝试解决这个问题,获取每一行的X和Y的浮点数据即可.读取文本文件每一行,判断是否为空行,是否符以分隔符号(,)分隔的两个数值.每个数值 ...

  9. java实现生产者消费者模式

    生产者消费者问题是一个著名的线程同步问题,该问题描述如下:有一个生产者在生产产品,这些产品将提供给若干个消费者去消费,为了使生产者和消费者能并发执行,在两者之间设置一个具有多个缓冲区的缓冲池,生产者将 ...

  10. 第一个HelloWorld!

    $.介绍 1.eclipse的基本使用 2.第一个程序HelloWorld 3.总结 $.基本使用 对于刚入门的java新手来说选择一个舒适的编译器能让你快速的上手java的程序编写. 针对英语low ...